From ac274b28969b5e1c25cc9532f3782bb74646ef12 Mon Sep 17 00:00:00 2001 From: Ingo Date: Fri, 26 Jul 2024 23:23:22 +0200 Subject: [PATCH] applied yaf changes --- .gitignore | 4 +- Gruntfile.js | 108 +- emoticons/alien.png | Bin 756 -> 0 bytes emoticons/angel.png | Bin 1182 -> 0 bytes emoticons/angry.png | Bin 781 -> 0 bytes emoticons/blink.png | Bin 972 -> 0 bytes emoticons/blush.png | Bin 865 -> 0 bytes emoticons/cheerful.png | Bin 753 -> 0 bytes emoticons/cool.png | Bin 965 -> 0 bytes emoticons/credits.txt | 9 - emoticons/cwy.png | Bin 877 -> 0 bytes emoticons/devil.png | Bin 1012 -> 0 bytes emoticons/dizzy.png | Bin 991 -> 0 bytes emoticons/ermm.png | Bin 983 -> 0 bytes emoticons/face.png | Bin 793 -> 0 bytes emoticons/getlost.png | Bin 792 -> 0 bytes emoticons/grin.png | Bin 867 -> 0 bytes emoticons/happy.png | Bin 792 -> 0 bytes emoticons/heart.png | Bin 572 -> 0 bytes emoticons/kissing.png | Bin 793 -> 0 bytes emoticons/laughing.png | Bin 912 -> 0 bytes emoticons/ninja.png | Bin 694 -> 0 bytes emoticons/pinch.png | Bin 804 -> 0 bytes emoticons/pouty.png | Bin 799 -> 0 bytes emoticons/sad.png | Bin 789 -> 0 bytes emoticons/shocked.png | Bin 780 -> 0 bytes emoticons/sick.png | Bin 783 -> 0 bytes emoticons/sideways.png | Bin 788 -> 0 bytes emoticons/silly.png | Bin 930 -> 0 bytes emoticons/sleeping.png | Bin 1039 -> 0 bytes emoticons/smile.png | Bin 983 -> 0 bytes emoticons/tongue.png | Bin 981 -> 0 bytes emoticons/unsure.png | Bin 763 -> 0 bytes emoticons/w00t.png | Bin 718 -> 0 bytes emoticons/wassat.png | Bin 810 -> 0 bytes emoticons/whistling.png | Bin 1072 -> 0 bytes emoticons/wink.png | Bin 791 -> 0 bytes emoticons/wub.png | Bin 1010 -> 0 bytes example/emoticons/alien.png | Bin 756 -> 0 bytes example/emoticons/angel.png | Bin 1182 -> 0 bytes example/emoticons/angry.png | Bin 781 -> 0 bytes example/emoticons/blink.png | Bin 972 -> 0 bytes example/emoticons/blush.png | Bin 865 -> 0 bytes example/emoticons/cheerful.png | Bin 753 -> 0 bytes example/emoticons/cool.png | Bin 965 -> 0 bytes example/emoticons/credits.txt | 9 - example/emoticons/cwy.png | Bin 877 -> 0 bytes example/emoticons/devil.png | Bin 1012 -> 0 bytes example/emoticons/dizzy.png | Bin 991 -> 0 bytes example/emoticons/ermm.png | Bin 983 -> 0 bytes example/emoticons/face.png | Bin 793 -> 0 bytes example/emoticons/getlost.png | Bin 792 -> 0 bytes example/emoticons/grin.png | Bin 867 -> 0 bytes example/emoticons/happy.png | Bin 792 -> 0 bytes example/emoticons/heart.png | Bin 572 -> 0 bytes example/emoticons/kissing.png | Bin 793 -> 0 bytes example/emoticons/laughing.png | Bin 912 -> 0 bytes example/emoticons/ninja.png | Bin 694 -> 0 bytes example/emoticons/pinch.png | Bin 804 -> 0 bytes example/emoticons/pouty.png | Bin 799 -> 0 bytes example/emoticons/sad.png | Bin 789 -> 0 bytes example/emoticons/shocked.png | Bin 780 -> 0 bytes example/emoticons/sick.png | Bin 783 -> 0 bytes example/emoticons/sideways.png | Bin 788 -> 0 bytes example/emoticons/silly.png | Bin 930 -> 0 bytes example/emoticons/sleeping.png | Bin 1039 -> 0 bytes example/emoticons/smile.png | Bin 983 -> 0 bytes example/emoticons/tongue.png | Bin 981 -> 0 bytes example/emoticons/unsure.png | Bin 763 -> 0 bytes example/emoticons/w00t.png | Bin 718 -> 0 bytes example/emoticons/wassat.png | Bin 810 -> 0 bytes example/emoticons/whistling.png | Bin 1072 -> 0 bytes example/emoticons/wink.png | Bin 791 -> 0 bytes example/emoticons/wub.png | Bin 1010 -> 0 bytes example/example.html | 125 +- languages/ar.js | 7 - languages/ca.js | 7 - languages/cn.js | 7 - languages/cs.js | 8 - languages/de.js | 10 - languages/el.js | 8 - languages/es.js | 7 - languages/et.js | 7 - languages/fa.js | 9 - languages/fi.js | 7 - languages/fr.js | 9 - languages/gl.js | 7 - languages/hu.js | 7 - languages/id.js | 7 - languages/it.js | 7 - languages/ja.js | 9 - languages/lt.js | 7 - languages/nb.js | 7 - languages/nl.js | 7 - languages/pl.js | 7 - languages/pt-BR.js | 7 - languages/pt.js | 7 - languages/ru.js | 9 - languages/sk.js | 9 - languages/sv.js | 7 - languages/template.js | 14 +- languages/tr.js | 5 - languages/tw.js | 7 - languages/uk.js | 7 - languages/vi.js | 7 - package-lock.json | 493 ++----- package.json | 8 +- src/formats/bbcode.js | 1201 +++++++++------- src/formats/xhtml.js | 1269 ----------------- src/icons/fontawesome.js | 115 ++ src/icons/material.js | 132 -- src/icons/monocons.js | 112 -- src/jquery.sceditor.js | 67 - src/lib/PluginManager.js | 8 +- src/lib/RangeHelper.js | 77 +- src/lib/SCEditor.js | 555 +++---- src/lib/browser.js | 10 +- src/lib/defaultCommands.js | 1059 ++++++++------ src/lib/defaultOptions.js | 204 ++- src/lib/dom.js | 116 +- src/lib/escape.js | 25 +- src/lib/templates.js | 155 +- src/lib/utils.js | 31 +- src/plugins/alternative-lists.js | 157 -- src/plugins/autosave.js | 110 -- src/plugins/autoyoutube.js | 106 -- src/plugins/dragdrop.js | 63 +- src/plugins/emojis.js | 86 -- src/plugins/format.js | 127 -- src/plugins/undo.js | 33 +- src/plugins/v1compat.js | 97 -- src/themes/content/default.css | 85 -- src/themes/default.less | 13 - src/themes/defaultdark.less | 31 - src/themes/icons/famfamfam.less | 56 - src/themes/icons/famfamfam.png | Bin 12429 -> 0 bytes src/themes/icons/src/famfamfam/bold.png | Bin 302 -> 0 bytes src/themes/icons/src/famfamfam/bulletlist.png | Bin 288 -> 0 bytes src/themes/icons/src/famfamfam/center.png | Bin 231 -> 0 bytes src/themes/icons/src/famfamfam/code.png | Bin 811 -> 0 bytes src/themes/icons/src/famfamfam/color.png | Bin 151 -> 0 bytes src/themes/icons/src/famfamfam/copy.png | Bin 634 -> 0 bytes src/themes/icons/src/famfamfam/cut.png | Bin 593 -> 0 bytes src/themes/icons/src/famfamfam/date.png | Bin 617 -> 0 bytes src/themes/icons/src/famfamfam/email.png | Bin 679 -> 0 bytes src/themes/icons/src/famfamfam/emoticon.png | Bin 696 -> 0 bytes src/themes/icons/src/famfamfam/font.png | Bin 512 -> 0 bytes src/themes/icons/src/famfamfam/format.png | Bin 308 -> 0 bytes src/themes/icons/src/famfamfam/grip-rtl.png | Bin 105 -> 0 bytes src/themes/icons/src/famfamfam/grip.png | Bin 106 -> 0 bytes .../icons/src/famfamfam/horizontalrule.png | Bin 263 -> 0 bytes src/themes/icons/src/famfamfam/image.png | Bin 600 -> 0 bytes src/themes/icons/src/famfamfam/indent.png | Bin 349 -> 0 bytes src/themes/icons/src/famfamfam/italic.png | Bin 221 -> 0 bytes src/themes/icons/src/famfamfam/justify.png | Bin 207 -> 0 bytes src/themes/icons/src/famfamfam/left.png | Bin 207 -> 0 bytes src/themes/icons/src/famfamfam/ltr.png | Bin 387 -> 0 bytes src/themes/icons/src/famfamfam/maximize.png | Bin 536 -> 0 bytes .../icons/src/famfamfam/orderedlist.png | Bin 302 -> 0 bytes src/themes/icons/src/famfamfam/outdent.png | Bin 347 -> 0 bytes src/themes/icons/src/famfamfam/paste.png | Bin 582 -> 0 bytes src/themes/icons/src/famfamfam/pastetext.png | Bin 579 -> 0 bytes src/themes/icons/src/famfamfam/print.png | Bin 664 -> 0 bytes src/themes/icons/src/famfamfam/quote.png | Bin 343 -> 0 bytes .../icons/src/famfamfam/removeformat.png | Bin 606 -> 0 bytes src/themes/icons/src/famfamfam/right.png | Bin 204 -> 0 bytes src/themes/icons/src/famfamfam/rtl.png | Bin 386 -> 0 bytes src/themes/icons/src/famfamfam/size.png | Bin 577 -> 0 bytes src/themes/icons/src/famfamfam/source.png | Bin 326 -> 0 bytes src/themes/icons/src/famfamfam/strike.png | Bin 267 -> 0 bytes src/themes/icons/src/famfamfam/subscript.png | Bin 367 -> 0 bytes .../icons/src/famfamfam/superscript.png | Bin 366 -> 0 bytes src/themes/icons/src/famfamfam/table.png | Bin 582 -> 0 bytes src/themes/icons/src/famfamfam/text_ltr.xcf | Bin 1726 -> 0 bytes src/themes/icons/src/famfamfam/text_rtl.xcf | Bin 1884 -> 0 bytes src/themes/icons/src/famfamfam/time.png | Bin 747 -> 0 bytes src/themes/icons/src/famfamfam/underline.png | Bin 270 -> 0 bytes src/themes/icons/src/famfamfam/unlink.png | Bin 589 -> 0 bytes src/themes/icons/src/famfamfam/url.png | Bin 512 -> 0 bytes src/themes/icons/src/famfamfam/youtube.png | Bin 314 -> 0 bytes src/themes/inc/defaultbase.less | 448 ------ src/themes/inc/elements.less | 98 -- src/themes/modern.less | 76 - src/themes/office-toolbar.less | 74 - src/themes/office.less | 27 - src/themes/sceditor.scss | 103 ++ src/themes/square.less | 89 -- tests/.eslintrc.json | 6 +- tests/manual/debug/index.html | 1 - tests/unit/formats/bbcode.js | 158 +- tests/unit/formats/bbcode.parser.js | 125 +- tests/unit/lib/SCEditor.js | 39 +- tests/unit/lib/dom.js | 30 +- 193 files changed, 2510 insertions(+), 5850 deletions(-) delete mode 100644 emoticons/alien.png delete mode 100644 emoticons/angel.png delete mode 100644 emoticons/angry.png delete mode 100644 emoticons/blink.png delete mode 100644 emoticons/blush.png delete mode 100644 emoticons/cheerful.png delete mode 100644 emoticons/cool.png delete mode 100644 emoticons/credits.txt delete mode 100644 emoticons/cwy.png delete mode 100644 emoticons/devil.png delete mode 100644 emoticons/dizzy.png delete mode 100644 emoticons/ermm.png delete mode 100644 emoticons/face.png delete mode 100644 emoticons/getlost.png delete mode 100644 emoticons/grin.png delete mode 100644 emoticons/happy.png delete mode 100644 emoticons/heart.png delete mode 100644 emoticons/kissing.png delete mode 100644 emoticons/laughing.png delete mode 100644 emoticons/ninja.png delete mode 100644 emoticons/pinch.png delete mode 100644 emoticons/pouty.png delete mode 100644 emoticons/sad.png delete mode 100644 emoticons/shocked.png delete mode 100644 emoticons/sick.png delete mode 100644 emoticons/sideways.png delete mode 100644 emoticons/silly.png delete mode 100644 emoticons/sleeping.png delete mode 100644 emoticons/smile.png delete mode 100644 emoticons/tongue.png delete mode 100644 emoticons/unsure.png delete mode 100644 emoticons/w00t.png delete mode 100644 emoticons/wassat.png delete mode 100644 emoticons/whistling.png delete mode 100644 emoticons/wink.png delete mode 100644 emoticons/wub.png delete mode 100644 example/emoticons/alien.png delete mode 100644 example/emoticons/angel.png delete mode 100644 example/emoticons/angry.png delete mode 100644 example/emoticons/blink.png delete mode 100644 example/emoticons/blush.png delete mode 100644 example/emoticons/cheerful.png delete mode 100644 example/emoticons/cool.png delete mode 100644 example/emoticons/credits.txt delete mode 100644 example/emoticons/cwy.png delete mode 100644 example/emoticons/devil.png delete mode 100644 example/emoticons/dizzy.png delete mode 100644 example/emoticons/ermm.png delete mode 100644 example/emoticons/face.png delete mode 100644 example/emoticons/getlost.png delete mode 100644 example/emoticons/grin.png delete mode 100644 example/emoticons/happy.png delete mode 100644 example/emoticons/heart.png delete mode 100644 example/emoticons/kissing.png delete mode 100644 example/emoticons/laughing.png delete mode 100644 example/emoticons/ninja.png delete mode 100644 example/emoticons/pinch.png delete mode 100644 example/emoticons/pouty.png delete mode 100644 example/emoticons/sad.png delete mode 100644 example/emoticons/shocked.png delete mode 100644 example/emoticons/sick.png delete mode 100644 example/emoticons/sideways.png delete mode 100644 example/emoticons/silly.png delete mode 100644 example/emoticons/sleeping.png delete mode 100644 example/emoticons/smile.png delete mode 100644 example/emoticons/tongue.png delete mode 100644 example/emoticons/unsure.png delete mode 100644 example/emoticons/w00t.png delete mode 100644 example/emoticons/wassat.png delete mode 100644 example/emoticons/whistling.png delete mode 100644 example/emoticons/wink.png delete mode 100644 example/emoticons/wub.png delete mode 100644 src/formats/xhtml.js create mode 100644 src/icons/fontawesome.js delete mode 100644 src/icons/material.js delete mode 100644 src/icons/monocons.js delete mode 100644 src/jquery.sceditor.js delete mode 100644 src/plugins/alternative-lists.js delete mode 100644 src/plugins/autosave.js delete mode 100644 src/plugins/autoyoutube.js delete mode 100644 src/plugins/emojis.js delete mode 100644 src/plugins/format.js delete mode 100644 src/plugins/v1compat.js delete mode 100644 src/themes/content/default.css delete mode 100644 src/themes/default.less delete mode 100644 src/themes/defaultdark.less delete mode 100644 src/themes/icons/famfamfam.less delete mode 100644 src/themes/icons/famfamfam.png delete mode 100644 src/themes/icons/src/famfamfam/bold.png delete mode 100644 src/themes/icons/src/famfamfam/bulletlist.png delete mode 100644 src/themes/icons/src/famfamfam/center.png delete mode 100644 src/themes/icons/src/famfamfam/code.png delete mode 100644 src/themes/icons/src/famfamfam/color.png delete mode 100644 src/themes/icons/src/famfamfam/copy.png delete mode 100644 src/themes/icons/src/famfamfam/cut.png delete mode 100644 src/themes/icons/src/famfamfam/date.png delete mode 100644 src/themes/icons/src/famfamfam/email.png delete mode 100644 src/themes/icons/src/famfamfam/emoticon.png delete mode 100644 src/themes/icons/src/famfamfam/font.png delete mode 100644 src/themes/icons/src/famfamfam/format.png delete mode 100644 src/themes/icons/src/famfamfam/grip-rtl.png delete mode 100644 src/themes/icons/src/famfamfam/grip.png delete mode 100644 src/themes/icons/src/famfamfam/horizontalrule.png delete mode 100644 src/themes/icons/src/famfamfam/image.png delete mode 100644 src/themes/icons/src/famfamfam/indent.png delete mode 100644 src/themes/icons/src/famfamfam/italic.png delete mode 100644 src/themes/icons/src/famfamfam/justify.png delete mode 100644 src/themes/icons/src/famfamfam/left.png delete mode 100644 src/themes/icons/src/famfamfam/ltr.png delete mode 100644 src/themes/icons/src/famfamfam/maximize.png delete mode 100644 src/themes/icons/src/famfamfam/orderedlist.png delete mode 100644 src/themes/icons/src/famfamfam/outdent.png delete mode 100644 src/themes/icons/src/famfamfam/paste.png delete mode 100644 src/themes/icons/src/famfamfam/pastetext.png delete mode 100644 src/themes/icons/src/famfamfam/print.png delete mode 100644 src/themes/icons/src/famfamfam/quote.png delete mode 100644 src/themes/icons/src/famfamfam/removeformat.png delete mode 100644 src/themes/icons/src/famfamfam/right.png delete mode 100644 src/themes/icons/src/famfamfam/rtl.png delete mode 100644 src/themes/icons/src/famfamfam/size.png delete mode 100644 src/themes/icons/src/famfamfam/source.png delete mode 100644 src/themes/icons/src/famfamfam/strike.png delete mode 100644 src/themes/icons/src/famfamfam/subscript.png delete mode 100644 src/themes/icons/src/famfamfam/superscript.png delete mode 100644 src/themes/icons/src/famfamfam/table.png delete mode 100644 src/themes/icons/src/famfamfam/text_ltr.xcf delete mode 100644 src/themes/icons/src/famfamfam/text_rtl.xcf delete mode 100644 src/themes/icons/src/famfamfam/time.png delete mode 100644 src/themes/icons/src/famfamfam/underline.png delete mode 100644 src/themes/icons/src/famfamfam/unlink.png delete mode 100644 src/themes/icons/src/famfamfam/url.png delete mode 100644 src/themes/icons/src/famfamfam/youtube.png delete mode 100644 src/themes/inc/defaultbase.less delete mode 100644 src/themes/inc/elements.less delete mode 100644 src/themes/modern.less delete mode 100644 src/themes/office-toolbar.less delete mode 100644 src/themes/office.less create mode 100644 src/themes/sceditor.scss delete mode 100644 src/themes/square.less diff --git a/.gitignore b/.gitignore index 56420edd6..70e3b5452 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ sceditor.sublime-workspace /docs /coverage .DS_Store -/codetests \ No newline at end of file +/codetests +package-lock.json +/.vs diff --git a/Gruntfile.js b/Gruntfile.js index b02462c08..81017d972 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -3,6 +3,7 @@ const libCoverage = require('istanbul-lib-coverage'); const libReport = require('istanbul-lib-report'); const reports = require('istanbul-reports'); +const sass = require('sass'); const nodeResolve = require('@rollup/plugin-node-resolve').default; const fs = require('fs'); const path = require('path'); @@ -86,12 +87,6 @@ module.exports = (grunt) => { src: ['plugins/**.js', 'formats/**.js', 'icons/**.js'], dest: 'dist/development/' }, - { - expand: true, - cwd: 'src/', - src: 'jquery.sceditor.default.css', - dest: 'dist/development/' - }, { expand: true, cwd: 'src/themes/icons/', @@ -120,11 +115,6 @@ module.exports = (grunt) => { src: 'example.html', dest: 'dist/' }, - { - expand: true, - src: 'emoticons/**', - dest: 'dist/' - } ] }, build: { @@ -166,9 +156,6 @@ module.exports = (grunt) => { }, build: { files: { - './minified/jquery.sceditor.min.js': [ - './src/jquery.sceditor.js' - ], './minified/sceditor.min.js': [ './src/sceditor.js' ] @@ -176,9 +163,6 @@ module.exports = (grunt) => { }, dist: { files: { - './dist/development/jquery.sceditor.js': [ - './src/jquery.sceditor.js' - ], './dist/development/sceditor.js': [ './src/sceditor.js' ] @@ -186,25 +170,6 @@ module.exports = (grunt) => { } }, - // Create the XHTML and BBCode bundled JS files - concat: { - dist: { - options: { - separator: ';' - }, - files: { - 'dist/development/jquery.sceditor.bbcode.js': [ - 'dist/development/jquery.sceditor.js', - 'src/formats/bbcode.js' - ], - 'dist/development/jquery.sceditor.xhtml.js': [ - 'dist/development/jquery.sceditor.js', - 'src/formats/xhtml.js' - ] - } - } - }, - // Minify the JavaScript uglify: { build: { @@ -220,24 +185,6 @@ module.exports = (grunt) => { src: 'minified/sceditor.min.js', dest: 'minified/sceditor.min.js' }, - { - src: 'minified/jquery.sceditor.min.js', - dest: 'minified/jquery.sceditor.min.js' - }, - { - src: [ - 'minified/jquery.sceditor.min.js', - 'src/formats/bbcode.js' - ], - dest: 'minified/jquery.sceditor.bbcode.min.js' - }, - { - src: [ - 'minified/jquery.sceditor.min.js', - 'src/formats/xhtml.js' - ], - dest: 'minified/jquery.sceditor.xhtml.min.js' - }, { expand: true, filter: 'isFile', @@ -248,42 +195,18 @@ module.exports = (grunt) => { ] } }, - - // Convert the less CSS theme files into CSS - less: { - build: { - options: { - paths: ['src/themes/', 'src/themes/icons'], - cleancss: true - }, - files: [ - { - expand: true, - filter: 'isFile', - cwd: 'src/themes/', - src: ['*.less'], - dest: 'minified/themes/', - ext: '.min.css' - } - ] - }, - dist: { - options: { - paths: ['src/themes/', 'src/themes/icons'], - cleancss: true - }, - files: [ - { - expand: true, - filter: 'isFile', - cwd: 'src/themes/', - src: ['*.less'], - dest: 'dist/development/themes/', - ext: '.css' - } - ] - } - }, + + sass: { + options: { + implementation: sass, + sourceMap: false + }, + build: { + files: { + "minified/themes/sceditor.min.css": 'src/themes/sceditor.scss' + } + } +}, // Manage CSS vendor prefixes postcss: { @@ -338,11 +261,11 @@ module.exports = (grunt) => { grunt.loadNpmTasks('grunt-contrib-compress'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-rollup'); grunt.loadNpmTasks('grunt-eslint'); + grunt.loadNpmTasks('grunt-sass'); grunt.registerTask('default', ['test']); @@ -352,10 +275,10 @@ module.exports = (grunt) => { // Minifies the source grunt.registerTask('build', [ 'clean:build', + 'sass', 'copy:build', 'rollup:build', 'uglify:build', - 'less:build', 'postcss:build' ]); @@ -368,7 +291,6 @@ module.exports = (grunt) => { 'rollup:dist', 'concat:dist', 'copy:dist', - 'less:dist' ]); // Creates the simplified distributable ZIP diff --git a/emoticons/alien.png b/emoticons/alien.png deleted file mode 100644 index 58a07677b338e60892f47c6724419d6a93b09ade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz4!3-n|x$R~#Ffhgk_=LDdL`3}m{~t)wA0#9s zz%2#3DmpqkCMG5}Ha0FUE;%_lB_$;_H8m|QEi*GSD=RBIJ3BWwH!m-*prD|rsHnKO zxTK_{yu7@orlz*Gwz09XrKP2#qob>AH7^yxEZ%$PlU_MAC$=FgwMV8Mb# zixw?evSit^Wy_Z@U$tu0>eZ{)tXZ>m?b>zg)~#Q^e#3?h8#iv;x^?TeZQHhQ-@aqV zj-5Mq?%ut7&z?O84jedm@ZjOYhmRaNa`foYW5|ETu{DMNl zB4V6DH4`wRHcjr_W!$?|qzn9~ejCo-U3d6^yy(n~QQB zMI0^~Z_B-X&3Vnn+}Z!*U+y#vs}`3o*w4T-Pkp<^Tro?2{`W70&gWJdor>SB`epku z)4y-mna#dh6Vf?*M?>Q5_tSSD{#bECSADOxv9v(fucWQ^^Cmp5Gky0bI5mXU?nTVzV#-Na~})l-aWNAyg?~YBx~O5!uLgAvtBmL;NWom zxZFB2Z~F`TuQ5KJtUSU0_Z!bT>vlKFEHUArcAwtG0>zmt`k3EKtnyeG=F=L&^P@$L u+s5`ss>zQgrL8xYi2P_f^Kin$tHx(Sy$tnEC%OT{mci52&t;ucLK6U`!(Rme diff --git a/emoticons/angel.png b/emoticons/angel.png deleted file mode 100644 index 4792225c2749989ddb78a3804dcd5bb9617fae0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1182 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy`!3-qNPStf`U|?zr@Ck7Zci{N{|38q#L~h#5 zKtTuzk%fx@8JKKbCcyPVbU`#CD|XifSp*@0ve8Z;#{kJ_7fuKp(*(Ft&L#ptcD5I1 zjt^IEAa|Z0SH2Hteh5!t5O;An@057%=~;X;3kB!Zi!ILJS(3rKB#U=xKHt(p{^ezY ztDD8v)C#TZm0aHUlC42`uMGo|eooEm^)h={uxx(od!E@arS60bg+oW`N zvhdxhqIcKJ-Q8+*uTSXScBO|Cg`Z3nemYI$=?sylizJ@U5q&;S?8QpyS4$*bEtPn+ zO!C!o$=53+-|SX;yH@J$dg-?tW#4U(ez#Hj-DcT$o8{hblzzWi=KU6#_uCcT?~?zx zL-ylNxsSW#KJHWccvSh*N!8DL*raOpXXJ6URM8k zP3!k%)!&!ZeqUApeNE%{4b9)Tw13~y`F&ga&sEhw*VX^r(D-vp>kp87SLg3d^}n|? z{@&I6cU$A%9U#*DcUR-zJHmGr|M#{2KL8@_ z{|~kQKLR41|BrP4KXUp1Sm*y^-TzPY|3B6H|5X3~Gq?ZG-TuD-BKQ9<-GON@B&WO| zm?#}eg8YIR7#KOZxMkGT^$pC-EUc`pZS3q5D{JeTnp@jDI=g1go;QE>rtN!=pE!By z?D_K-uRMMJ^5x4{?>~I{{N>xv-+%wT{=fYw(2Q)}xpMZ*6;&6%*lol**W7t(;Kyqt7T-)&AA3A*nqln4tI|ZM%G#~C1 zJ}xWMw{CXi>?{@$llKujr8SD)+}Nn>UZy)gXeN`;72oJRUo`?)IQViRuLRFpz$!9@ zd;Zp>;}4bH`DCp&*jM@T&b3K8=5`YvPj$MTrc+c9 zvAg8qmT8-0>RrPom|OZRmfofAKih2O>U|pOr)J2CDcq|RHN7f&^rvLp28P6hgvq6R zJ*Ut1eJ!4p%3P$_#B;`G(kwBtS(9we@CZ2SFfe>rJ8`GnuXEbP0l+XkK D{&Ew< diff --git a/emoticons/angry.png b/emoticons/angry.png deleted file mode 100644 index 7bec8e4bab65d39fa8be3bcd58ba833d3f2154be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 781 zcmV+o1M>WdP)+}4Jch)?7lhN}T&oKa2 zHTt>X-011Wuuf(@&njhkD4M2ad|k}+adUzBtk)jAHXdu<%0bHp34&EB1j?0Y`n?c; zypW0euZjcThPIstJeFl*HGTa|CISr_jCbfTVW!x$7Nad1gsYSo+$q6l52t`{OJiv4 zOi*#lg)w~7_{-&(=+KAf0V(&J~8O^9hPFeO-&n44|c+46gpIbp|yE1e~>lC+$VZ~lBL6}}yX2$xFel=zW|ui0p|4B^8i@NFx=z^^%Q zf1HjV@1mponj2z}r(~~D|GwAK;n|pv!0sYK7(j&%7Sp_EeIELM%qDF6V~Jp6`smf0 z@8j^vJ&ACCpN*lvaxu(+;dOa5-TzZIdcMqn!UQ3J)4Xl?uy5~7so98`I_Sc`vR++<)>(xmd*cxUCsUmJ*Iy3VWQbJ00000 LNkvXXu0mjfU{`#- diff --git a/emoticons/blink.png b/emoticons/blink.png deleted file mode 100644 index ff529f1216550e49223946ee805750560cee6141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 972 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV3G;&32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*f&-02u zFRT2#ruO@?;_u5!zppC)zNYf~hU)K|>c4LRk;d;^n!j&r{JE<1=c@9bTk3y+?7Kju z`S+&E-&;VW`uDE--v^q1A8P))t@7^<5UKsUtMc!G`o9O7{~l@md#v^EiPryns{ik) z{lBmJ|GwJ)2SB9$|DpQ-$6Eh^Qctx1Kh^sGR2!Ho?l}Z{1Cxt-NswPK0|O%`7q^U> zx`CO6m332dYkNm$*X()okDoYs>g@R|&tJZL`Re_LPmDJ|X#ka4c)B=-R4^td9AT1> zkZfp}+3oM->e|%bEqSDwV-x4=TNTr$RzzfSZgymyY4NnjTis{=wfpx3l2wkMWD!dV zFPdvmesdYG_wz4i&#g{wZf1!*`bJ$ZFg*PJj>5Z-?)~EN4isCU&|i02=Ihzn=BwAU zpV}hYo>|Py+WO{KLy`l-w3R*^1Q@tZ{qPNK?^wy)xl5$nbHM_ye3e}!|{`DF^ zep6ueJc{CJX3va(YRZv!I}zm;$C^aTv*!n_3+4l>V-_wx1al9xLX a!N9R`TtBz_)LH-f@2?$_T|NN$ zkNo$~gee5+1efOYiRR-OD~_wFaNZEyOoiiGO6(V{*p8ccwN=aXc45eWzs02ZJ)yB? zA;0G*=BaR;x8f2a_wCehFO48A?z?GlN%2JsNym)5-=bmP&}eEF@O>&{y@dgSIqQcj za2&VbzK|NOrlDY_P$b+*{o~$!RY*@;u=sDTVZnZJztxCqnI8Kj6(4)W@uG1QC#!s!!xNsu5o;TUW9uw>Ianilse?rZ zSZ_r3i2dSvKwS44ac>m8o3F(-GJ&_9Vt86NoJHjVrEsXHFlYNx0laOiAgOO6j`12? z3v^;=df4?<<`z=dP9a;PC23|N?*}P)(K?FzH9~1y#1Fakyf^mTRSiOU-&28YbOQD{ zY82L__8%56+tB?!yvUfC(n}xARmJI&hJmy!?)T^A r>rV>oK*4drhi@F0@BXU5{;&KBuZV}c&5;fV00000NkvXXu0mjf6a%Ls diff --git a/emoticons/cheerful.png b/emoticons/cheerful.png deleted file mode 100644 index c7c5cb8499f07ff2a47573f5cb8f6b054c96688a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmVRvCV6*Z3k;x@!E*iw(Vz+ZQHhO>*9M=^Ex*@W|GscQ|RvhEC74T(&nM- z?N(w>TuOXM6d3;T{XTLITJz)^>#mo0QA@mzx)J94$U97@XffCingK^>`FT8k< zBlsC2Xd|HwaXwM~?|a^us#L?+sDr76(bBON3$<#@7ArBFB*7oAx`Ce+Vrn(81EJ2YL)Zw*i(eJ5T^5e{PEm9IbKgt;m;S0TvsxandyI@Sva z=bco2E45#x#8jpP{m16Qz+>AdR#WJx##}c4ZD^y6w9a@;`RhTW1VKgcbrC)ilFkdVj zo1~j2s*qX|Bvt_-5_V_+s?bzN!h9(S1JLq|CkqF}!tse58H|*b+Yw7xV5OZ=!_umP zu||QJYzaof{L%80$0}i2OIQ#O8s-)uaD~K5E4{czB^JtLm`V-C;1ORGeeA}V z%oR#`R$F55un#(ZaL3EH+q3Y>l^^zhC*N_$L}DOj^CX+fhK~B6=T{FLe8!Pw|FT0Y zWHj^}4W@tLfiZe>Qz=2#V8~=(td$+~2FnuOa0bN;@UOSw;_%yZ&gj|igOO8yt19dJ z+Y_zdy5Z-i95-GZRxV#J&|D6^?2N+C+|cv82fBZ8NB;XRI6y5vf2;k*%hv`A>_l$5M}W!&F5WSCa}6$WKFH$x?b`1Eg~ByNbD@(JlV7QO7_|&`MZ;a?oJiHyI$sApTNEC@((8pKA9@`beho98A4ANi9Meq{Cu9sisN$!Sil6sLf8Hzed7td(L-L@3g6GGe7~&r^St8E%PK#wsr|mJ`1`Wb@2kqc zuc`dLq5Au#`tMsBzi(;&zOC`+s?wjU%71RD{{gb^0+Ht5n<{^A0g>w8yXt=*X#Rbu z`R}&MzdJyr_V2FBzk90x9;p9&p!x5S*1yME|DI_5zo+{Dp4$KWs{ik+{eJ*N>i-|A z|9_LYcR#bQuaDoJ_jOO-D--WPu>}hKb$hKi)-XU6gsFF!QM=;zH1y?Ei$ZRRa%%323}dPJZ2@};&<`E%*hr%QXD zY+$H%EsJQ7U_GjK oscargruno@mac.com -Andy Fedosjeenko, aka Nightwolf -> bobo@animevanguard.com - -Copyright (C) 2001-Infinity, Oscar Gruno & Andy Fedosjeenko - -You can redistribute these files as much as you like, as long as you keep this file with them and give us the proper credit. You may even rape them if you please, just give us credit for our work. \ No newline at end of file diff --git a/emoticons/cwy.png b/emoticons/cwy.png deleted file mode 100644 index 58ee08f80b3b5d8b0528bb2ddcf784b9f3e54e9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 877 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV7wCG6XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TkKDKaW)ai_TtR(;mQr<&hz8S_uET4-CsT!=P7`@LL*(fq ziRW`fpU)F}u~Pcg5{Xw!C0;F)e6?Ki&2FW)Yo*?Kt z>Gzvu-fxk4zg^+|F8Pl;WIyhd`?yQ)<36R2N0mRFRQ}wCsn?kQTujA{rf4E@8{LOU)K70UghUy z_1~A(eqUApeNE%{4b9)Tw13~${&P#~&u#6$H`V{%()fE<^WSZae|LaL^WOvQ|MxWi z-v=VC{||sj`~O32U~KOEE}svKX7!RFzhGcIb8>OZsHq#6Sy)*&HMh2Rbau_2H~;vF zlc&y}zw-R$%a^a-fB3|B^OFWpsiLQgV@L&K?uF*6&5ixB&8sWZ;vMa+dN}X6H(ix92~X myjSin)tm13$L^E9Eo0W*fa-mcM_&TNm%-E3&t;ucLK6Twvy<8Y diff --git a/emoticons/devil.png b/emoticons/devil.png deleted file mode 100644 index 7d8226a277a6df575c5396daa51a4e24f348befd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1012 zcmYjP4NOy46h800()WfIhBo|(mR6<1F@_s6)G1UbQQXAJPZ>65Zo+g*F&k_+nA9I| zDk!4qSY#^>Qzl_ZK!-zw8DaoMtZUhzB2a;q6q&8%&rs>zZOx*|cfWh`o$sD=bMHAJ zjo-*|_jd;XPTVF*0^S$l<-<^zR}WbJ1|WIT50hdMLMa|hir57lyc)j{F~2JE|2Mm` zvS21T(xn8rSmfmRa5mB`%Tlr^XDs6~G9PBEh@B#2 z_BSf}+YK4b zYx=)Fr;ryt%sr2;ne0X@6`Uu`lO}5}w2NaE98!~=TkHpYvG?_=CHAYCO098pwC~XM z@N`{$Q(essW!}Y$RkgR5ra45C=?wM2pt@pWnky+s6pR#neb?XjGC5}=-d-s#!kJc5Gs0B7R!PymVCC4ZK z{n@y!sf4>~TZDX^Y!r2Es(zHz$nl+%{aTs(?v9CF%+B*Y;tP8d%lD9g-VzjjCe3UJ z(+x*;`ZlGTN{Sawo6>*xJA78H;VBNBG3~CVw;y5W9u=1zl%8p6P{EtQ**ktqEj@() O2I6AlC6}Xj9{CSQAEAZ- diff --git a/emoticons/dizzy.png b/emoticons/dizzy.png deleted file mode 100644 index 82184642f9284288a0eb154fa17cbb0a37f53f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 991 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVA2Ti32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*f&$9|Y z&ny1Ctn%}k+V9IszppC)zNYf~y6W#6s=sfl|Gou88ozI8{=Tj8=c>}5tIB__tNyv6 z`sbGVAE3xxAkzGMOXcrf^}i1^|31|GcU$G(9UxNscUR@#J=K2?)c-xw`uAA#-(#(R zPqhBuQ~iHW?f-q%|M%7YKL8^2{}0vwKhpUBNb~<=AkzB(MEn0!t^ZH8fhi>F`U@3c z(oru7@(X5QVC3ZDmQhnTFtf0-Zfb6A@96BBJ#YT;6DLodJ%8o-%a<=-z5nou@#ZHD zpi+BJ7srqa#^i(}OcD~34GlB9{heH0oBF#Yk2G^^;(UFpV%pS-h)mASj;u2+p7waF zpPOa5aIxYskG{#AIw#gWu`0aRl^Z?n{M+nvrIXUxIX89P^p9G#Zrwi7j^D40bzCDG znrwdQ7GK?-f1mHz+oOrM?l?Fq?*5nh%3+^X$BUId8w41*PW?E0gGYQ$*z`wwoFXA7 z=kF^N4#;2@SU)>z_M5c~A|YpA$8JhI-1hbL_4U!acdS;r$E~9A`m$ZRtVhb*TcMk8 zcP+ZJq_Ih9Tj^cy>nm2TkK9{SmtI=6Vx~gCgmC@ME4^zkdVOVm^{V&g#D7*c3dg&n zpI_Nh>Nj)Ey{M_8vKd;(xIU@1Z%U3ztPBmUbj+$)(5z&wf&$9|Y z&ny1Ctn%}k+V9JXzb`BOzN-BDn#%7Rs=sfl|Gou88ozI8{=Tj8=c>}5>#Bclss918 z?*ftL-wqERmi@(X5Q zVC3ZDmQhnTFtf0-Zfb6A@96BBJ#YT;6DLodJ%8o-%a<=-z5nou@#ZHDpi)~;7srqa z#^i(}OcD~34GlB9{heH0oBF#Yk2G^^;(UFpV%pS-h)mASj;u2+p7waFpPON~aIxYs zkG{#AIw#gWu`0axNq6?Nvv0G{l}<`$=iJnF(?4p}x_zmi(@MYY`^DoOD7HYMzwUI* z*R|1C&6_&DJu=A6Td-h4?EYO=0SrzdY7ra^tf_yNDRN$0y2G1^HT2W+Jch#S%^jLs zPu}BlaJ;(bp6ctXSFf*)UcPSMj@?T4xK%V>U$#qsyQ?(&`kKhiMPbo_Q)Zh41RUA6 zF8$#v)9kSIQHJ|hTiIUm5zsiXdiu>Pw$&HAM7h(-%+lO{z5dW3qn|f7n0ZT8QF?Z0 zSjmEw651zb%be=VY<(K~>M85WhmCw)Z#FO(^7MIo_4IOlG-Y7puz6u}Hnxdrj<3l9 nM|S>{I!#kk&AJMOWJU({^u#v7H8Y!mVb9>{>gTe~DWM4f#N@^6 diff --git a/emoticons/face.png b/emoticons/face.png deleted file mode 100644 index 04ad4b7a2aaf344fb64c6d11d5d4269311cc4128..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmV+!1LpjRP)u_2(=mzY|^9m zcNzY8p&0jHl>xC1ue%C(B2`cIe*H`_g54&>hN}^`aP-}b`F;~3t$NJtR^hXU^B~sc z8J=AV>TbC(ZL;|n1rH}2HAuQ^0Z$#^u0zsQi-euvArqnExR_lG zW>8;me77925i^p`T1E(?YL7=~(q1D_+EX38+ZFib3EtB$sB|fK`lB~wA=+a?f(GE0 zAmTe$!@*gDgq04zM~~nk6()YGzyp`33-nYe`09qY%lJ@}u9~HY>%XeGq}`0zfDz#a z4Q4l1;irdl1o)B^Y_o1xAx?)2*YXIQk{o8l2MvfcX)w20hW0lK1=uJBy@4hz;=?8y zSO($D3~_b>2lR+EstK%u<)b12PD(+a|ELVCBRpt;295JodNGIIik%PaX7peNsECIhDHrY z4Cx8eBHE;af2RynKbOJrUI8AwG);h~FTSzA`SYoK_;<+=X;6tn;ysD?X*mJSw`mYL zs)T<>6{deJgXiNy{CF4d-Pgj9f+9UVMpFk~D};A*C4zh92p?7wz|nUFf_r4}Zmhu6 zkEM+5d@LI@Gs%zMYA=UR?#YJd`%=vQRgO6V<~CID_o<&sG5%!{tZ(Pz!#groe>p6E zecg9yI(~XE8_loe!}Dn&+#eO7@!4Gba91Yoy*O?4*Vig9*cYfKD!}n~{%`dc>{|9W X#NehlfXChQ00000NkvXXu0mjftdMl% diff --git a/emoticons/getlost.png b/emoticons/getlost.png deleted file mode 100644 index ac87dcea2511cb5276398989cb23c5f434c3e462..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792 zcmV+z1LypSP)eTtlbqs(* zg?rp`VQesQ#OcJ#L0o7iEG{S~qEJk{_2`X>IQm`=#*1Ze^lD)5Qe*UQ3I2H{ z6AxdP09J<(M-v_)P9#RZe<2I@VJ$q<26*QfdivJmU|b7VuNu2GGJN%TDp*}U=SVoA z_Kr*Awz~h2a3bH50sd7Zux0{QP4KT6;afDoGo^!jKn-iX42|z);f{-AH&|}4FoF2K z=)+uiX7unc8<~X3c$k16P*<`z0duzmv{{okF46MnNz25X%7x zeFw2bamJz!-U$+R%1M}yxz93~a7!q(SlblvP^*5b94rxt2rc~c8hFN3aJI^@SCEIf zPtrq#19JspZlZm2d}5F!z&tJ7v>FEk3fSu<*#092J+G!RVYg8DcEPKe+?;sE)$q?! z;(|c3z|fG4Mlhp>XG95CyA0;iJZyZQiC-T`WWqOu!gC(KJ^|)xG2Gp9HXP~&CC{lz z!i#39_ft%!fV)cuYn2Gwzh`6Vqcl8vWgHWp9lWuB`1iRqSgS>Fb;ttS!#k!Tl$_|G zPYzd`6xK=+cK*!9+UM!`^}Ylq`<^+3LWYix(RSlo=`hpE+3Un`wnzeE_HC~f!CaJ! z?O(GvS=CcXpqwps^rBu4Up$b6wV$)G_g^mdi-^Kp`p&`jZ`s)RHUsnTr{dFl5~5!Y z!PnPAG%vqBnuP8*QnB`BI#xeRL+6Xh_=Se};N@{quCM49>?=eUVdLrI%c5Vfhspnm Wr;i>N%`IgB0000w3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_nW2O zZ5u#5KOR;5bW-v2UYXB_kU4b|T_)qmdtB8}g-G=JaL_;W+`&n@*oK*n7l(){~C z^Y25=e-G6EJ<|I3So7awt$$Cn{y$Lv{}6~Y{yzdD&Hs-z{yzqiTK}JD{s+oF(f;F@2U~D=#C$9oVvwBI8UobG9Ik~uH)YJ{kEUc`Xnp@jDI=g1in}7Vo$x~;~UwQuW z<;z#^KYU`m`AGw)RNT|WF{FYq_X2Y{6N8Au!<^ge%x`bInsa;G**E{*#GT!7{QgH( zf&ZNjDhVlK{)rnkDs+q(tDR?AY+X`VyLF+4r%$!JQ1JA5V3TdM#!`i%OW)r!sB$p!%dGjLwpq|Mb-Dk+ z1cL{kf9~OTmwwF3a9O=H))Y|)8jJaXi1i50`LS-c(BjwW{;st%OM z?pnC*DZ`@q2NUK>1qSWlOoJFh$P)<vrd=TL4e zq4DMmQWl$jRfs6r>rbt8DnKY((vC>TB#QH-3t8tIIr|`B2_9p?UC!#;qNx`DunF(6S5i5 zD*xr*w$K=DzgrJ?l?n^Lmf-%&Qib#ssqmF8Zxzv2O|&)3AtH{sjsFv7jsyJ$cE;aUEGi!>+Kr2%M@7pxd_cK@J%;Kg|BUXA)n7A(5FXu zgc8Rkl5v57WVC}}Jp$cY`07-!?mJp{vqh-zSH^NiDX+HyIw) zvxG$>wE96I)4<=Tf^)A7OFtE2^4%Ofa7l^~o)-DT{`!w6bKu-3gRfr2TOuhF?A5Yp zy;TigtrE^XGA#d6h}n;F@xz_`uD=qF$fswbXS7uDYA)<_bMAw3c&imGAUJj(kiovS z7)w7Cux#(68K9g+etL diff --git a/emoticons/heart.png b/emoticons/heart.png deleted file mode 100644 index 451058d6d02646eb1b0fac70cde05c02c9864d28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 zcmV-C0>k}@P)xZEyy?R`y=9^UeZv$sUe$-T>!cM1 zkZs(pGk#hUyl8@t?1I~_6oe^S&+{gww`K}`Pun2e|5ghJq1?$-bU1ip+5b#-9XiM417EWeG zqHAlLugifCw6Ze^;286VCy0w(P~asa`g?;X3WA@if~=>o=$g+;gLevmTf)I^9#*Wk zxC`uqMlLBQ_t!)!QpR{(6ug-R&JVOgm!+6w7dQ@nD^NB}2>`F8fakTv@qSiptpo@R z$3Z(DvUIvaGkmSsO7jf(yP)CM&JFdYf!)gfJZNM#fZqxJS6={J%R+Dw5WwsJ0000< KMNUMnLSTaAWev6f diff --git a/emoticons/kissing.png b/emoticons/kissing.png deleted file mode 100644 index 28d775242312a519611bcf2b29752c4765abb2cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmV+!1LpjRP)0YJwXLyT+YM@4acxAkZQJg(eec?~?H$i#GkE*`U-j=O+9c2Md5+I90M-=_ zu0JO^k`&@3;yI$0urr+IvXi(?M89~#a^lqou1UwnH%rj7RRK?v4(@s_x_*=3_vZ_7 z-<4?)+Hl(h!VQFt==$pELby8&2n?7I9A+qO#A=TLz9ub}_9^h`Lpc!I{?lheETQJ+ z3sUAAewK0P(6|}lDGM-d1*WVBPg)QfBXPe0{#GrV2NgK{W+84qFL_qz8!1d9zS{Cm zDFTB=geNR4AsJ!$ACiX0%q;aaX<*+a!_SZNOg|@5#lq7bxjqB_P6N%tOfnYW{1dV{ z4aUrQOqdZGq2+gK;XbOs+^=Q0|FTp;dWu;1%I3F9c&Xt@77{FE5hfYVW70&kG$PQe zhqqRRiCH@>D zzpr~QNyU#3WTN5aTugtGkEsvyQ1?tWzP~da_gs{c`1?xm!9Gva6E23+T$b>IU041B XKE9Q6@a!0~00000NkvXXu0mjf6^?Pr diff --git a/emoticons/laughing.png b/emoticons/laughing.png deleted file mode 100644 index d65f35ec82967bee26777dbc0deb39f2af387807..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 912 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVEh!|6XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TbxYw3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_nW2O zZ;^bzUH1JhnUA}qKkk$NcvSJzNyX25Wj^nd{d`FN^GTJ@m(;$TQT=*E{_AnYZ^z}o zoly98Qt{gvrEh0czMoR~eqQDKWwoD|ReoMm`+ZgU_cfK@*HwStQ2l*V{r4>(()fK# z^Y?9yKi5_N+)({;DtY|3EcQwEsWV`u|k>&<~M^z(k;4666;Q zOa+`=+%jtF24)sk)=kZ=?H!$6v**n}e&Xb*v*)iofBEv|tM?y1G2Z;70aU8y>Eakt z!I*oYxysm4g7v|TZFA4$FWxry*0$W)8_)iJ^X8hx;rF#Q1~LjSYigEqvtLiX+xsqFON-BS)4DHLo_VU@y|#GmNhMQB z$3+_d&u}_eO=WtJQL7W|(Qx9&zFgJ-Aq6=$>*BTZUkX%K9$)98B-rn^Sn&A4qIx#= zMT_2PwRvfXaK)|Ro$jqDwM_r;iWVlu|36;^Y-L+i`07F8d`0_zJILuOm_Y_pTGa=Le7M z8Ve-lzyNNAhK7cwrlyvbmbSLGuCA`WzP^EhfuW(Hk&%(Hv9XDXiK(fnnVFfnxw(af zg{7sXm6esXwY80njjgS%ot>S%y}g5jgQKIPlarIPiGZ`Sv#YDCo12@vyZfugnPbQo)!S;F^?e$Rl&J?$5$AJ>U2H?cy<3?@tNUTw}y-$S3&ip@LTKlS}pyxv!cS z1tzi`-Y+h`$?;M9-_)P7CKq28t1`4CMjt*jS+ylxpH(tQVr5_DX(=AQd&SNH84^z) z?h^4nxz+TX1ml{GN~t^6$sGE8XD?&#_5Qgwum12SO!y_eg8k>DZ#}}i$96JQ9PXc@ z)x_L+$D~2MGN^J+w?lJf#BTQ{cDWswW~@%wu+%SfQ~UQbs^0hW9t8AUnx@L6aH#aH zxTsF0rM9EgMTzTk%EIpn8Ou&lin}fPF(YJ>>W|#o13J5B^s_Ywl{v25zFJ{%)8T~6 qGetffR?iVh@%psum#XCNA1sd;7O;N0m%t4SM+Q$c}^?_?*vG2_c^dC~e(`tabNsr#&6!`u5 zRNQxE48%8td^h3Y#4$wgS5K$G-EBl**n;4gz)aU>Z1fx9Yt>`5M1@ZuN`&~9V<>hz zq4DMmqL!L}R3e4GnSsTJLR)i)k2n?Cv@6f|pu0rLTX}I~k$ORF*Sr|in zb?}``1V+pVPg_~SGR6vqq~X7%G*d0?1q%H9IM4KRB3ddu?UCza;qNi>EQIX*6B5Ca zSt%BN9vY|R_vqoSR$=kiEZl!tw2+=66~1!dtqfYKiI!&hPry==V1@zT&zNbJCIkiy z@HS|$c2I^NABq>k7p20s@d6csv|L)&wh}&1o54((5gatY*QCLEjtuRuCktVtRA_h6 z%OK4V(=6I7VfcQ^1kenF10-xzlQ0`&AEpT5l2qt$)@cwJH1KjTEs+TU!yCT5j_GuTKMW!u;*rB;j2{qaCfW_zAP1<{?Ju1uouhW zZ&r)t&@3o;OwSS)jneFggiHf}lM2ov8J2%a$JDz?c;J#KAv|sKkNx!@PbR@xEQ7B> z#kmqQ3HIp-EsHkV)bQ0Q;VhJ4<(G8KeUywJ?&N*_m2hm{dM4UN%ayMt!%mfRm&xI+ zQLupEYj>#(_Jf&N{vnNJMUTdTVwQO8?baMVzB>+c-=$;i&rGZzBo1WKbq1DyOvl0( zDHwk%5g*(hvwL&c+`jImy!`k;9GYKF#M~#znEfybjnBm6ds^Z>7e(#fzIJJ_&l63A ii{Wd2wtIu!Oa21oag#O*h5@4h0000YNwYxKE{O{Bq-P~s+`6jn;zB#9=>zo4M zq{98V=gJ@%?vQXI--H4FX(KRW0;WyyPZ{AGH^4KXgS$-)YpD$7pT*;WtAplPtWX$A z{GRb;53Pgh?;t3qMT%JdsM(QE4RP3#Ms2wGKC)(o>c? zc=|MO)+w-(A;N#pM=;@gd|}IIo(x_p7gJ2e7Z^ARCiNQ`()WZO-hK^S4GOGgiO~8< z3=`J#g=QNqdMQIHi6;>-p<9PC^!AakUQWUkjC>c%gbRG3#ag3)hyE*-Bb4w(gckl$ z4Lm(6IICq?NlV7aH!%VFCUP zu?XgjBrN_L&&dj23J1k3Y&^X~H-{gd2*=Fd30T>egw+fpJ&C>(vG`vC=6;RE=;u-R z_K{FQb2vi#dWz2Fzh}eI_(2qAevHBNchRVSGXnomiBDc1eB}0Zhz9!((LmT38{h97 dsllF9_5&MblaH!wQGZEPJXDZ6~N#Mv;!Jef=={5njf1iZ+ zo(u<9hRRMN3}ToVrK`S9g1uM+Z?z7-I)XiG;VIX^m8(SWaS4`w6br8GU?ylhq2lES zLc6jzizw`G(&PRcVt_Uy&}u}W#Q=Y!j=s4Il(3$X;LM*%c=^7N4lX-d7|vL=_n$O) zYqSV78-`>I!w5_oXrzi*OBFC57Gd+})Y9dQFuw4%Po9s2yF>&3U|?9%I)t7;vmX9> zEtRpKlb~~JI^KUQjFaBN7yh#6uT<)4phZ68SfZ9;1Z?b-M-dlqlh^Q?t-$2@fXoSF7MDkimXRgzn9$$oYY0I-4*2ZTAm}G$!71 z6#}(P+Q5@Es0mIMs8PXNqJZm?80G^R=vbA64R1$s!k_uV+dq0L9Oh#}xU*%{9o7mO zukmnaNnkxHK=-CpH2oWo4;~5Sgtv`e*sFJZ83*ez0bG|Q6y#dsE0c4uXE{81GPo{^ z>0i&5RJ1Khz=k)eb*nhX=&h$@+o=1@uL&^k&w%};5YF>r5-`}a2=)^KnD?fmdqWDz zj(!>img%CcH`(E^`0XgPtxG}Q&NTEhLI0j~dhXtsf{qo5sQ)Vt3tkT&bvR6Me7*Zf z7&d+oh3uc>(6%H2tqbFE<(n9+e=`E_JQO;~@iqAY`#mFzVH+fizD;q!&MQ{|T1$wX T^SL{P00000NkvXXu0mjf0kd`( diff --git a/emoticons/shocked.png b/emoticons/shocked.png deleted file mode 100644 index f3dfb11f8d22ddb7d678befd190322f0df7d330b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 780 zcmV+n1M~ceP)%Z-~r5!eHV=V(9x9l3*TC!ZD$NbDBd<*J|vJC}Hc8W2;hxuO5#D_w8OxurHzV zj!VPVJO0RGqDxMVWnftcEa~80)E+#u_sU_c5uxtAB;0Xv=qeZMDU2Y#&;KwLj!88y zA_+STyI;`2HABN6 zl*8O0!rEVHc;xDEPI{(L_-5YwDKu0S4UL3C!4lms^050wHD#%SV^jfas|4Hm8Tjq- zXioT=P}n_FDuR=Si$zW*6lj@JNMN@HYbh|Iowke zILicV-h{X(#`H$l8=#^od@NCbG{lmY{#lcvS0b8qx4T&;g5*!o6U>mwQ8^*E> zZ2p;y<wT=QzvmpDrKh4Y+NgUg9(r0ib9E-Hjagn9>hn{v@oN&3l|K~)idpAM zFJN={;(;hE|D25N|5CA&PvoW2bqY3qOUCNA37C057N6b|;n^Glx37n2UVeKt3LS66 zV)@H>EPWP-wil!E3k~tX%fkYY&p&wKVeTF3jdDiX^EVMA<@NM@BxVUd&vS9TUq&SzICW!9`=)~;pNuV*u8 zW;SSJG-+is>tMB>%w#i_(QXpE(^L+pSEGI`JE@?OsDyO7IwC9~fmuAsH7LF-t8dxavmvPErYi{8c-vz;ww2V2}O_V^uK zi92|b4{)R(RpW!Ju!&PvWyW|3Q=|!H3t9+H$ zc&o1SR^Q;QxxrU^o3HLRU;Q1vhI{(y#B92i3khQeSdTV~X&i04;&7C&f;rFqut`+9$Q(+~4G{fByb_@!x!VUWZn4 z&MwypDi>GA|L>9vt-Z3mk8_qd%RIGN<=lmPd!p{M9ptLC)Ct`G=j~Mn-BvT@C#s%t zGw(fq7jArEt6Kqsg4v_5OI|U!WP)sma(ylZQFMKv2EM7(e57hms>Y_qh8J8yjQxXT!#TTQ22BG zIsQ8dAWkBlBWei?!)Y!%iQDXm+fSHGy!ya3!8r700(vr3a5fp>sMn+GHyM6^J{I>~ z83fUW+xie5P8>sYef4xK933WX3><;YVTRIXto4}SZqj3^P=!w)ihyX#F&w*FsJr=s zfcb`>6&$=Zek8n8M*-7E15-!CJ9!kg#z@?6f~QpvTZsx~Z^q*0^ZaK;>`q}2@m2ae ziP#u4!#i;lOGri>#V{m2|AcS>jZ_Cqt^z+l&LjPt2$Tv>d*u2McsflqiX%xTk%%;N zB$$aKS-94zhoeG;xnGlT|7C$fdWux|O4?fqJXP-`2kZiqM-oRcBEQjVgsWDA<@6N% z_)wS-z9RmKawHEg6H9*IOEVZ_M7wN?!rB?>J3oPfp`c&8hr!q-w?h~YKa=rO=MMAA`- zWYowAnRn2@LU)Z4maJsVeie%!?hX;cm!-nfAG#_CmI66E4H}-#)&Plz4J={NkO5o$ zdX@=n`7$j0lz{Pfqwv5b0YZ4%&V&8+A5TWYRv?4BR>f1==+t4eTPvWn7HiEKxT}@0 z<)vWpmjq0I6pbJ5Zrx$*V$Ltp|7; diff --git a/emoticons/silly.png b/emoticons/silly.png deleted file mode 100644 index d4497d9aee01396181aea5545c6fe0dca0109df9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 930 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVEi566XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TbxYw3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_ZubN zZRu6+iEh{=8S_^FGRQY^K?aLX}uZLy7 z9+CfgT=Cmcxo^kiznxI{c2e=%8KrM$RKA~5_kYYQTz8m z{of<4e~&f)J<axjH`bc<@hWMQr@qlfRFtst7oT{fXaQUAxoP`o;g{3duU9-ViwP z^JoiGH_s64NKH?|Qx-DngyP!LpG#4!_pVJlrkv&E)?A#z(C`H(RTJcxRbY zd(4MXPQdljG(WxEocw$pzYuCw-AHKZ*8hBkwztDnm{r-UW|D6p}* diff --git a/emoticons/sleeping.png b/emoticons/sleeping.png deleted file mode 100644 index 2b97a8033ee0907a0600015f7d1c576b6cafb9f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy~!3-oDVtf1<7?|_|d_r8q9XS5~{|_W-fufy2 z#sbM`7fuKpVvDnhK(-fWjt^IEAa|Z0SH2Hteh5!t5O;An@057%=~;X;3kB!Zi!ILJ zS(3rKB#U=xKHt(p{^ezYtDD8v)C#TZm0aHUlC42`uMGo|eooEm^)h={u zxx(od!E@arS60bg+oW`NvhdxhqIcKJ-Rl#&w_WMsMByh>g`Z9nc{)Sn=^}~eb3~ud z6ML~z`qdJNS4$;cEt7n;T=Mk_$v3-|-maB;yI%V3M%i~8q~C3nez#fn-DbJ>n`Pc_ zk$Jye;r%Z8k2~c)?vnesPwC@PvTidzMWC~c1HdCNu}?nRKA~A|9)BP=UJ7X=T&}Q zR{wcT>-S~V-XUseBoP2=}<&EGdPf8W&leM|fIEuG)Dwf|gI{c~OY&kc<~x3vBM zxp#H`-c|MxWi-v=VC{||sj`~O4j|Brx3=l>(!|BrS4KL(O||DWjo2daFc|Np7p z|EKyJJ56r^6OejIkY6wZ10yFFw~U&)ftiJsbyIU|dq-#2?0NH#pE!By?D;FtU%q_# z>ivgLj5j}N0F`EXx;TbZFy>xho-Q3A(DpDPSNYr8+}mDjuWUPPv@LLV@7en8#mRe* zpFeZaT|r2&FG60SWvyi3%e{<&m(3LzA98dA@G7sX$aIVmp7gsdtzys2g?2@}yN`+I z-}?XOeDllHYjXO_8mxIvYt>zik9w$*$UFZypk`~Lmg2j3jKVY&6{ zH}mil&p*Gke|CNQHUBaOKApcGRA--0-#pXj(d1tzU$*{jNRHO|A7IuTq%qUQ?c>u@ z<%TWF??Tubj|g^IiC+JHj_H%!4k3k)6*^MA7EiA8ZDRQO-FJVt5N~_^%lKHUhKY3^ ze+`+KSZh`tfBrpyQQb_N$KL5-fq}%2Ws~pOY)um>C^-4Hyz2gWhX=dEe}6l-b8$Bt zgY|OrdsA1IlhBw>zi+Dlz6C@Yzi(;&zOC`+y6T@Bs()^&{{gb^0+Ht5n<{^Asrr%D;Q6{~oCSd!YI6k=DP*n*Sba{d=PI|DNjqdusphtNy>Q z_WuD8ssDcnL>m7e0g>ka#~S}114*s_Pc;7n6+hAb|5WS$Q|t;0FJHcT|KStk%}*LYrM8|fjv*C{ zsS`{WU2_m|+dsSK&&LPvEy;hhSz;wA>BX5k#0e<=<8)2dtA*dM*xxpBj_O?P$vm-NJi9X9PTp5}XZ z(c4>b)3U!_zJAQ;c3$?=?`zApHu%?VaF6|8cKGq4h+l>ITW7`Rbsjl)IegN=e2aJM zL?2^L3ucVkf3az_4fVboFyt=akR{0C-T%{{R30 diff --git a/emoticons/tongue.png b/emoticons/tongue.png deleted file mode 100644 index 73da3e34ba3840435b21ef55c80188ea3841f60c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 981 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV3H5;32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*yCeLJJ_{iOW&QwrbDt9-w#_Vc{r&&w)5 zuc`gMtn~Y;^6zUZzptzQzM=a2ruy$&K&0{emgeu<8h@@T|GBRE=Z5N^Tk3y++`B-e z`S+IU-@EF6A87u4sQK@X+P}Lh|L&>&d!YXBk=DP*n*Sba{d=PIpNZjrZu44EyIT4g8&ya+rN5k9l3~ z61ORL-psu5sp8<^h1Tuem0gj;7;_=; z=h?bIH&+#dGv(gWx2&ud?0Yi#Z{Ngu`cK~Mo?rj}&yPRo{+)c?|er4V(VBj-&y85}Sb4q9e03`9*5&!@I diff --git a/emoticons/unsure.png b/emoticons/unsure.png deleted file mode 100644 index 87c7599719d6be5d1766b657921f69e45cedf2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 763 zcmVwym<)wl`SYiq}T8w#~6UZQHhOt6Y^%;h+1?=%qA#$@g+~zUzAdfb$Cd zp1du#-1|{hWxtED204Di|A;=s6(3!7t2tj+E7~`LO;f3jGir@#=+R7foEHe1k7`>uEJo(mdxLhU>m*= z&Z$c%_}J%~CaI-G0d2krdq1R+Ze#@Ug*UwSWGJlN8aO6sWZ-|E^6TA77^@^$*q@9y z9|+>4*YSnlW&DyzQ*}-s6M_N>PkCFv8s>T#Rx?wv`<-x3_%&bHI+ibiolO^~DYOr$ zU}=V(U}EIl`plJjuA4;AGBW6>QxKSn9;k=A>YL zOB{B+8p;X3gv$N}w+kU};YxCV!8{ zTlWQW!W&!<_SQomM?qgCfTdnSi_eY3-YX~go1!mB#qz#H%>EODT`$w002ovPDHLkV1lV$WP<7?rClj>j2XnZ}Q`0a%9x05PAFRTB)s{Z?i=I>kD zf3B<{v+C^3>V$SDwFo`SR8K51$xse$oI% zlBbJfNCji=1?J*rM+ue(-MP0bvu|&EYnJ-vzy00!NpF76l-3pg$|-E<=F+pgPIQB2 z>GKYcD^=+xudb|Ct+*1HCmDOMy83Rc%%&5sHNt*&YE1og(C%q?r=`}RkhNhe4}I@# zaB`R_tG{HQ{*5ILZ+CpiS+_co_rjiAA3vAfi+IBm3U+`=Mk83Ml8`0XfZQHhL+jhq@X$Ie(bLOTQWGCuPe%IeG|3e=D zg9bDgnoGm95?7(ZMF`D4SSutjWeU)DCk1(1qNwnrvrw(e z6vA31V@-mV3Z0H7h3hjFmWyHf$S1;N)b5L>!cJ$QM*EHrONEp+hYF~au#bh&D0f^r z>~&IDO2sg~O-JvIMAYty^bqFP-bi5`ZL5_6RNBbVAajMtY*iBU=L?{Jo`$Xq@yK4w zMmoz`xcSD~Xx1l|G70Q8L|X48sh3ii%w8>lrC0>h`*f)9CZYX!49?C7ros)*!XM@j z4}|)0D$H2|)*M=ey;edboTx?uTcw!DgfM6Fpna5ruJiF|+!cwr|N2wm_wEz>#MNaH z&^}Iq=>v~7iB@7Q6*8!(KUVDM$ oHrO?UOoEOhlY8fVgB?sh0XTn_nkWgd9RL6T07*qoM6N<$f_mL}CIA2c diff --git a/emoticons/whistling.png b/emoticons/whistling.png deleted file mode 100644 index 3940f0d8215e74f6fb86126b8005e3f95c2eea28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1072 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6I!3-n=6T)m57?^?rd_r8q9XS5~{|_YTiK3lA z)3%2G7!bzNLly%gY3pcgwDB7F$y*w60fjeT(RZKFN&}qz-h79OxB0 z(I9YQg2<_Mp;OBh&b11j>lV4xCwyg<+_i}!*ET8LSSWROz1+R+N{{v{J)SB0c&X&$ z)iO_}3O}78@^q2J(_IQL7E8QXDg9!V#N@P4Pl`(5%McgTL+CHHZk(#HexACD@3+9UVrr0VCr@}Eztf4-#k<)Gr1 zLrP!HXnZ}a`1QE**Rv|$jw*gTru6N&(zlZ;-_EFiJFE8nl*;#Ws^2ebeZQgcR z{C}+b{|ON3|9`3nOiNj_OPhg-%%CL5FPMRWk&}y?S6oI`P2IrE!pb@zv8<`NwWG6Z z_PqHkw;eft;^gVG=dV0}`SR8K51)Sh3aaus0n`)g>Eakt!I+$Igik_3vY}ySxQkSZEI&{(v*_bC(hb$74vq@nPxyi0{>r<1c;=3#BVmACgz{uQOTWu~a;i7)D zHPhip>8bSGd)xEh&$C@E_WjG(GLg27&5cJxmDShW*qeTSU2J!_-t7&kFPG%hI&Rpp zB>nc6UhDF=w>D-Ro0ZERzFW%mMB`Cboo=h;y7#x#{(iHrb90*CMzfw!w(iZRc1+*$ z&3~@_{*_zTZCtv|;&PmXP~M#=yPu)FXV0dJT1sZF{Aadljzgixj+<&}PoAZy9A}yN z@+9|0<<`xe!46J)<}Wrhm~)UpPJfZtu3cV>PJC>VWngH2RKk-Owr3wOk{CQ){an^L HB{Ts5%ZKa> diff --git a/emoticons/wink.png b/emoticons/wink.png deleted file mode 100644 index 3d1a9cc0725bef494cd960fcff0ad294e44444c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmV+y1L*vTP)*z?q>i6$z6;)!IZ!Aj-g@-LFr>bhh~7*Y9L*Zo8`S9jTY`UHiNnL! zg@V5!#D@t3h!ctK?_Y?Ay;BR%paI?yMo-szto3T)YF1;pNQSQ-j{<+YnF-iWsJ-LT z;DyFNBrJk&!T|rY5tuOn(7YiD6;AP-wQ%OYfkL zLc1jbCg?pwE%f%0uwG8W6pVZp%fbbr&|F9 z$R{y-gl!{fVjk!X;rL$3Hls9ggKDg`DPS*^VDXPcG`$+d!bYL+?X*|pcue5w-IR_A zBx8(*WE%K~)bMmE;i{FvoSlrh@8j_617R$DLnu7w@#{ljE)>JvDCh356#fx4Nj62p zYWN0NrhvOa25W%`i@zse;-hFhdSx&R&)&VTfB5&gXjltHaMj7UODtvJ?NPD_Yb|oP zYNW8{i?H-(0%kss!LRp)vg~_y2!)J}w$WnwTQM-x%-KuCa8^lJ!0A_qAMOAE002ovPDHLkV1k#Le$W5_ diff --git a/emoticons/wub.png b/emoticons/wub.png deleted file mode 100644 index d5faa2b605b5d4890adb314da8754dd360d5c8f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1010 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz5!3-qlM(p{{z`!IK;1l8+uE6pC|9>D!3ly!u z1vEBFfiqf(J6aLMh9GAFg=_`BY$btQCBa-Zkvs+dJZq%I_Z6M^85I-53#8q;!{6l=6y^^|Cp5dF}v_%PQj=0iqEN8pHs6xXXJj) z%KuzY@+B+(OMc1Mto*Mz1z&RtzvdQx%`5umlkg2l7M6aisQyu0_M^P&M@7|-%IaSg zRlh2#e*qblHNUEAe$~|es;T=`TlcH3{#QK^HT-G-qQ>9VHNR_Wf7jOi2C^HQem6D! zt*`&v(D1jR@o!_(Um&-+`EOg>-;VZwP0jzBfvDwQOUu8uwtpQR|2jMVb#?u3ZTa8Y z`o9f`+Wxn<{qJc1-`VlMs}qE^Zk$bptaCE9<7_*7lCh zuG#bEA3t&O)Y}a<<`Q^X{z3V#8tKV;^zI*8DYq15BCW_8~exJ>DgF92RBg4McxwqqUZ*K#l zZF$$X^~T>=a_z|b!)NXrZZH1S+3}%plktBO?e8s3v(`R+b;qK7wYkw|Uax3X+;aei5s`ykzeTk@1Jb^;>%g4TJKDI%F}i!mH5oD+4r<#sgPhd z!)4pvk9-`udq1abJHJjtgy}#?e0JM()qj(GD^A|{^XuKaTX!(;E(mlhY6&R4bm?dtl|a{u%{|NCv2Gos23oiZL50^^6l)78&q Iol`;+01z+H<^TWy diff --git a/example/emoticons/alien.png b/example/emoticons/alien.png deleted file mode 100644 index 58a07677b338e60892f47c6724419d6a93b09ade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz4!3-n|x$R~#Ffhgk_=LDdL`3}m{~t)wA0#9s zz%2#3DmpqkCMG5}Ha0FUE;%_lB_$;_H8m|QEi*GSD=RBIJ3BWwH!m-*prD|rsHnKO zxTK_{yu7@orlz*Gwz09XrKP2#qob>AH7^yxEZ%$PlU_MAC$=FgwMV8Mb# zixw?evSit^Wy_Z@U$tu0>eZ{)tXZ>m?b>zg)~#Q^e#3?h8#iv;x^?TeZQHhQ-@aqV zj-5Mq?%ut7&z?O84jedm@ZjOYhmRaNa`foYW5|ETu{DMNl zB4V6DH4`wRHcjr_W!$?|qzn9~ejCo-U3d6^yy(n~QQB zMI0^~Z_B-X&3Vnn+}Z!*U+y#vs}`3o*w4T-Pkp<^Tro?2{`W70&gWJdor>SB`epku z)4y-mna#dh6Vf?*M?>Q5_tSSD{#bECSADOxv9v(fucWQ^^Cmp5Gky0bI5mXU?nTVzV#-Na~})l-aWNAyg?~YBx~O5!uLgAvtBmL;NWom zxZFB2Z~F`TuQ5KJtUSU0_Z!bT>vlKFEHUArcAwtG0>zmt`k3EKtnyeG=F=L&^P@$L u+s5`ss>zQgrL8xYi2P_f^Kin$tHx(Sy$tnEC%OT{mci52&t;ucLK6U`!(Rme diff --git a/example/emoticons/angel.png b/example/emoticons/angel.png deleted file mode 100644 index 4792225c2749989ddb78a3804dcd5bb9617fae0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1182 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy`!3-qNPStf`U|?zr@Ck7Zci{N{|38q#L~h#5 zKtTuzk%fx@8JKKbCcyPVbU`#CD|XifSp*@0ve8Z;#{kJ_7fuKp(*(Ft&L#ptcD5I1 zjt^IEAa|Z0SH2Hteh5!t5O;An@057%=~;X;3kB!Zi!ILJS(3rKB#U=xKHt(p{^ezY ztDD8v)C#TZm0aHUlC42`uMGo|eooEm^)h={uxx(od!E@arS60bg+oW`N zvhdxhqIcKJ-Q8+*uTSXScBO|Cg`Z3nemYI$=?sylizJ@U5q&;S?8QpyS4$*bEtPn+ zO!C!o$=53+-|SX;yH@J$dg-?tW#4U(ez#Hj-DcT$o8{hblzzWi=KU6#_uCcT?~?zx zL-ylNxsSW#KJHWccvSh*N!8DL*raOpXXJ6URM8k zP3!k%)!&!ZeqUApeNE%{4b9)Tw13~y`F&ga&sEhw*VX^r(D-vp>kp87SLg3d^}n|? z{@&I6cU$A%9U#*DcUR-zJHmGr|M#{2KL8@_ z{|~kQKLR41|BrP4KXUp1Sm*y^-TzPY|3B6H|5X3~Gq?ZG-TuD-BKQ9<-GON@B&WO| zm?#}eg8YIR7#KOZxMkGT^$pC-EUc`pZS3q5D{JeTnp@jDI=g1go;QE>rtN!=pE!By z?D_K-uRMMJ^5x4{?>~I{{N>xv-+%wT{=fYw(2Q)}xpMZ*6;&6%*lol**W7t(;Kyqt7T-)&AA3A*nqln4tI|ZM%G#~C1 zJ}xWMw{CXi>?{@$llKujr8SD)+}Nn>UZy)gXeN`;72oJRUo`?)IQViRuLRFpz$!9@ zd;Zp>;}4bH`DCp&*jM@T&b3K8=5`YvPj$MTrc+c9 zvAg8qmT8-0>RrPom|OZRmfofAKih2O>U|pOr)J2CDcq|RHN7f&^rvLp28P6hgvq6R zJ*Ut1eJ!4p%3P$_#B;`G(kwBtS(9we@CZ2SFfe>rJ8`GnuXEbP0l+XkK D{&Ew< diff --git a/example/emoticons/angry.png b/example/emoticons/angry.png deleted file mode 100644 index 7bec8e4bab65d39fa8be3bcd58ba833d3f2154be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 781 zcmV+o1M>WdP)+}4Jch)?7lhN}T&oKa2 zHTt>X-011Wuuf(@&njhkD4M2ad|k}+adUzBtk)jAHXdu<%0bHp34&EB1j?0Y`n?c; zypW0euZjcThPIstJeFl*HGTa|CISr_jCbfTVW!x$7Nad1gsYSo+$q6l52t`{OJiv4 zOi*#lg)w~7_{-&(=+KAf0V(&J~8O^9hPFeO-&n44|c+46gpIbp|yE1e~>lC+$VZ~lBL6}}yX2$xFel=zW|ui0p|4B^8i@NFx=z^^%Q zf1HjV@1mponj2z}r(~~D|GwAK;n|pv!0sYK7(j&%7Sp_EeIELM%qDF6V~Jp6`smf0 z@8j^vJ&ACCpN*lvaxu(+;dOa5-TzZIdcMqn!UQ3J)4Xl?uy5~7so98`I_Sc`vR++<)>(xmd*cxUCsUmJ*Iy3VWQbJ00000 LNkvXXu0mjfU{`#- diff --git a/example/emoticons/blink.png b/example/emoticons/blink.png deleted file mode 100644 index ff529f1216550e49223946ee805750560cee6141..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 972 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV3G;&32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*f&-02u zFRT2#ruO@?;_u5!zppC)zNYf~hU)K|>c4LRk;d;^n!j&r{JE<1=c@9bTk3y+?7Kju z`S+&E-&;VW`uDE--v^q1A8P))t@7^<5UKsUtMc!G`o9O7{~l@md#v^EiPryns{ik) z{lBmJ|GwJ)2SB9$|DpQ-$6Eh^Qctx1Kh^sGR2!Ho?l}Z{1Cxt-NswPK0|O%`7q^U> zx`CO6m332dYkNm$*X()okDoYs>g@R|&tJZL`Re_LPmDJ|X#ka4c)B=-R4^td9AT1> zkZfp}+3oM->e|%bEqSDwV-x4=TNTr$RzzfSZgymyY4NnjTis{=wfpx3l2wkMWD!dV zFPdvmesdYG_wz4i&#g{wZf1!*`bJ$ZFg*PJj>5Z-?)~EN4isCU&|i02=Ihzn=BwAU zpV}hYo>|Py+WO{KLy`l-w3R*^1Q@tZ{qPNK?^wy)xl5$nbHM_ye3e}!|{`DF^ zep6ueJc{CJX3va(YRZv!I}zm;$C^aTv*!n_3+4l>V-_wx1al9xLX a!N9R`TtBz_)LH-f@2?$_T|NN$ zkNo$~gee5+1efOYiRR-OD~_wFaNZEyOoiiGO6(V{*p8ccwN=aXc45eWzs02ZJ)yB? zA;0G*=BaR;x8f2a_wCehFO48A?z?GlN%2JsNym)5-=bmP&}eEF@O>&{y@dgSIqQcj za2&VbzK|NOrlDY_P$b+*{o~$!RY*@;u=sDTVZnZJztxCqnI8Kj6(4)W@uG1QC#!s!!xNsu5o;TUW9uw>Ianilse?rZ zSZ_r3i2dSvKwS44ac>m8o3F(-GJ&_9Vt86NoJHjVrEsXHFlYNx0laOiAgOO6j`12? z3v^;=df4?<<`z=dP9a;PC23|N?*}P)(K?FzH9~1y#1Fakyf^mTRSiOU-&28YbOQD{ zY82L__8%56+tB?!yvUfC(n}xARmJI&hJmy!?)T^A r>rV>oK*4drhi@F0@BXU5{;&KBuZV}c&5;fV00000NkvXXu0mjf6a%Ls diff --git a/example/emoticons/cheerful.png b/example/emoticons/cheerful.png deleted file mode 100644 index c7c5cb8499f07ff2a47573f5cb8f6b054c96688a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmVRvCV6*Z3k;x@!E*iw(Vz+ZQHhO>*9M=^Ex*@W|GscQ|RvhEC74T(&nM- z?N(w>TuOXM6d3;T{XTLITJz)^>#mo0QA@mzx)J94$U97@XffCingK^>`FT8k< zBlsC2Xd|HwaXwM~?|a^us#L?+sDr76(bBON3$<#@7ArBFB*7oAx`Ce+Vrn(81EJ2YL)Zw*i(eJ5T^5e{PEm9IbKgt;m;S0TvsxandyI@Sva z=bco2E45#x#8jpP{m16Qz+>AdR#WJx##}c4ZD^y6w9a@;`RhTW1VKgcbrC)ilFkdVj zo1~j2s*qX|Bvt_-5_V_+s?bzN!h9(S1JLq|CkqF}!tse58H|*b+Yw7xV5OZ=!_umP zu||QJYzaof{L%80$0}i2OIQ#O8s-)uaD~K5E4{czB^JtLm`V-C;1ORGeeA}V z%oR#`R$F55un#(ZaL3EH+q3Y>l^^zhC*N_$L}DOj^CX+fhK~B6=T{FLe8!Pw|FT0Y zWHj^}4W@tLfiZe>Qz=2#V8~=(td$+~2FnuOa0bN;@UOSw;_%yZ&gj|igOO8yt19dJ z+Y_zdy5Z-i95-GZRxV#J&|D6^?2N+C+|cv82fBZ8NB;XRI6y5vf2;k*%hv`A>_l$5M}W!&F5WSCa}6$WKFH$x?b`1Eg~ByNbD@(JlV7QO7_|&`MZ;a?oJiHyI$sApTNEC@((8pKA9@`beho98A4ANi9Meq{Cu9sisN$!Sil6sLf8Hzed7td(L-L@3g6GGe7~&r^St8E%PK#wsr|mJ`1`Wb@2kqc zuc`dLq5Au#`tMsBzi(;&zOC`+s?wjU%71RD{{gb^0+Ht5n<{^A0g>w8yXt=*X#Rbu z`R}&MzdJyr_V2FBzk90x9;p9&p!x5S*1yME|DI_5zo+{Dp4$KWs{ik+{eJ*N>i-|A z|9_LYcR#bQuaDoJ_jOO-D--WPu>}hKb$hKi)-XU6gsFF!QM=;zH1y?Ei$ZRRa%%323}dPJZ2@};&<`E%*hr%QXD zY+$H%EsJQ7U_GjK oscargruno@mac.com -Andy Fedosjeenko, aka Nightwolf -> bobo@animevanguard.com - -Copyright (C) 2001-Infinity, Oscar Gruno & Andy Fedosjeenko - -You can redistribute these files as much as you like, as long as you keep this file with them and give us the proper credit. You may even rape them if you please, just give us credit for our work. \ No newline at end of file diff --git a/example/emoticons/cwy.png b/example/emoticons/cwy.png deleted file mode 100644 index 58ee08f80b3b5d8b0528bb2ddcf784b9f3e54e9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 877 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV7wCG6XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TkKDKaW)ai_TtR(;mQr<&hz8S_uET4-CsT!=P7`@LL*(fq ziRW`fpU)F}u~Pcg5{Xw!C0;F)e6?Ki&2FW)Yo*?Kt z>Gzvu-fxk4zg^+|F8Pl;WIyhd`?yQ)<36R2N0mRFRQ}wCsn?kQTujA{rf4E@8{LOU)K70UghUy z_1~A(eqUApeNE%{4b9)Tw13~${&P#~&u#6$H`V{%()fE<^WSZae|LaL^WOvQ|MxWi z-v=VC{||sj`~O32U~KOEE}svKX7!RFzhGcIb8>OZsHq#6Sy)*&HMh2Rbau_2H~;vF zlc&y}zw-R$%a^a-fB3|B^OFWpsiLQgV@L&K?uF*6&5ixB&8sWZ;vMa+dN}X6H(ix92~X myjSin)tm13$L^E9Eo0W*fa-mcM_&TNm%-E3&t;ucLK6Twvy<8Y diff --git a/example/emoticons/devil.png b/example/emoticons/devil.png deleted file mode 100644 index 7d8226a277a6df575c5396daa51a4e24f348befd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1012 zcmYjP4NOy46h800()WfIhBo|(mR6<1F@_s6)G1UbQQXAJPZ>65Zo+g*F&k_+nA9I| zDk!4qSY#^>Qzl_ZK!-zw8DaoMtZUhzB2a;q6q&8%&rs>zZOx*|cfWh`o$sD=bMHAJ zjo-*|_jd;XPTVF*0^S$l<-<^zR}WbJ1|WIT50hdMLMa|hir57lyc)j{F~2JE|2Mm` zvS21T(xn8rSmfmRa5mB`%Tlr^XDs6~G9PBEh@B#2 z_BSf}+YK4b zYx=)Fr;ryt%sr2;ne0X@6`Uu`lO}5}w2NaE98!~=TkHpYvG?_=CHAYCO098pwC~XM z@N`{$Q(essW!}Y$RkgR5ra45C=?wM2pt@pWnky+s6pR#neb?XjGC5}=-d-s#!kJc5Gs0B7R!PymVCC4ZK z{n@y!sf4>~TZDX^Y!r2Es(zHz$nl+%{aTs(?v9CF%+B*Y;tP8d%lD9g-VzjjCe3UJ z(+x*;`ZlGTN{Sawo6>*xJA78H;VBNBG3~CVw;y5W9u=1zl%8p6P{EtQ**ktqEj@() O2I6AlC6}Xj9{CSQAEAZ- diff --git a/example/emoticons/dizzy.png b/example/emoticons/dizzy.png deleted file mode 100644 index 82184642f9284288a0eb154fa17cbb0a37f53f29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 991 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVA2Ti32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*f&$9|Y z&ny1Ctn%}k+V9IszppC)zNYf~y6W#6s=sfl|Gou88ozI8{=Tj8=c>}5tIB__tNyv6 z`sbGVAE3xxAkzGMOXcrf^}i1^|31|GcU$G(9UxNscUR@#J=K2?)c-xw`uAA#-(#(R zPqhBuQ~iHW?f-q%|M%7YKL8^2{}0vwKhpUBNb~<=AkzB(MEn0!t^ZH8fhi>F`U@3c z(oru7@(X5QVC3ZDmQhnTFtf0-Zfb6A@96BBJ#YT;6DLodJ%8o-%a<=-z5nou@#ZHD zpi+BJ7srqa#^i(}OcD~34GlB9{heH0oBF#Yk2G^^;(UFpV%pS-h)mASj;u2+p7waF zpPOa5aIxYskG{#AIw#gWu`0aRl^Z?n{M+nvrIXUxIX89P^p9G#Zrwi7j^D40bzCDG znrwdQ7GK?-f1mHz+oOrM?l?Fq?*5nh%3+^X$BUId8w41*PW?E0gGYQ$*z`wwoFXA7 z=kF^N4#;2@SU)>z_M5c~A|YpA$8JhI-1hbL_4U!acdS;r$E~9A`m$ZRtVhb*TcMk8 zcP+ZJq_Ih9Tj^cy>nm2TkK9{SmtI=6Vx~gCgmC@ME4^zkdVOVm^{V&g#D7*c3dg&n zpI_Nh>Nj)Ey{M_8vKd;(xIU@1Z%U3ztPBmUbj+$)(5z&wf&$9|Y z&ny1Ctn%}k+V9JXzb`BOzN-BDn#%7Rs=sfl|Gou88ozI8{=Tj8=c>}5>#Bclss918 z?*ftL-wqERmi@(X5Q zVC3ZDmQhnTFtf0-Zfb6A@96BBJ#YT;6DLodJ%8o-%a<=-z5nou@#ZHDpi)~;7srqa z#^i(}OcD~34GlB9{heH0oBF#Yk2G^^;(UFpV%pS-h)mASj;u2+p7waFpPON~aIxYs zkG{#AIw#gWu`0axNq6?Nvv0G{l}<`$=iJnF(?4p}x_zmi(@MYY`^DoOD7HYMzwUI* z*R|1C&6_&DJu=A6Td-h4?EYO=0SrzdY7ra^tf_yNDRN$0y2G1^HT2W+Jch#S%^jLs zPu}BlaJ;(bp6ctXSFf*)UcPSMj@?T4xK%V>U$#qsyQ?(&`kKhiMPbo_Q)Zh41RUA6 zF8$#v)9kSIQHJ|hTiIUm5zsiXdiu>Pw$&HAM7h(-%+lO{z5dW3qn|f7n0ZT8QF?Z0 zSjmEw651zb%be=VY<(K~>M85WhmCw)Z#FO(^7MIo_4IOlG-Y7puz6u}Hnxdrj<3l9 nM|S>{I!#kk&AJMOWJU({^u#v7H8Y!mVb9>{>gTe~DWM4f#N@^6 diff --git a/example/emoticons/face.png b/example/emoticons/face.png deleted file mode 100644 index 04ad4b7a2aaf344fb64c6d11d5d4269311cc4128..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmV+!1LpjRP)u_2(=mzY|^9m zcNzY8p&0jHl>xC1ue%C(B2`cIe*H`_g54&>hN}^`aP-}b`F;~3t$NJtR^hXU^B~sc z8J=AV>TbC(ZL;|n1rH}2HAuQ^0Z$#^u0zsQi-euvArqnExR_lG zW>8;me77925i^p`T1E(?YL7=~(q1D_+EX38+ZFib3EtB$sB|fK`lB~wA=+a?f(GE0 zAmTe$!@*gDgq04zM~~nk6()YGzyp`33-nYe`09qY%lJ@}u9~HY>%XeGq}`0zfDz#a z4Q4l1;irdl1o)B^Y_o1xAx?)2*YXIQk{o8l2MvfcX)w20hW0lK1=uJBy@4hz;=?8y zSO($D3~_b>2lR+EstK%u<)b12PD(+a|ELVCBRpt;295JodNGIIik%PaX7peNsECIhDHrY z4Cx8eBHE;af2RynKbOJrUI8AwG);h~FTSzA`SYoK_;<+=X;6tn;ysD?X*mJSw`mYL zs)T<>6{deJgXiNy{CF4d-Pgj9f+9UVMpFk~D};A*C4zh92p?7wz|nUFf_r4}Zmhu6 zkEM+5d@LI@Gs%zMYA=UR?#YJd`%=vQRgO6V<~CID_o<&sG5%!{tZ(Pz!#groe>p6E zecg9yI(~XE8_loe!}Dn&+#eO7@!4Gba91Yoy*O?4*Vig9*cYfKD!}n~{%`dc>{|9W X#NehlfXChQ00000NkvXXu0mjftdMl% diff --git a/example/emoticons/getlost.png b/example/emoticons/getlost.png deleted file mode 100644 index ac87dcea2511cb5276398989cb23c5f434c3e462..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792 zcmV+z1LypSP)eTtlbqs(* zg?rp`VQesQ#OcJ#L0o7iEG{S~qEJk{_2`X>IQm`=#*1Ze^lD)5Qe*UQ3I2H{ z6AxdP09J<(M-v_)P9#RZe<2I@VJ$q<26*QfdivJmU|b7VuNu2GGJN%TDp*}U=SVoA z_Kr*Awz~h2a3bH50sd7Zux0{QP4KT6;afDoGo^!jKn-iX42|z);f{-AH&|}4FoF2K z=)+uiX7unc8<~X3c$k16P*<`z0duzmv{{okF46MnNz25X%7x zeFw2bamJz!-U$+R%1M}yxz93~a7!q(SlblvP^*5b94rxt2rc~c8hFN3aJI^@SCEIf zPtrq#19JspZlZm2d}5F!z&tJ7v>FEk3fSu<*#092J+G!RVYg8DcEPKe+?;sE)$q?! z;(|c3z|fG4Mlhp>XG95CyA0;iJZyZQiC-T`WWqOu!gC(KJ^|)xG2Gp9HXP~&CC{lz z!i#39_ft%!fV)cuYn2Gwzh`6Vqcl8vWgHWp9lWuB`1iRqSgS>Fb;ttS!#k!Tl$_|G zPYzd`6xK=+cK*!9+UM!`^}Ylq`<^+3LWYix(RSlo=`hpE+3Un`wnzeE_HC~f!CaJ! z?O(GvS=CcXpqwps^rBu4Up$b6wV$)G_g^mdi-^Kp`p&`jZ`s)RHUsnTr{dFl5~5!Y z!PnPAG%vqBnuP8*QnB`BI#xeRL+6Xh_=Se};N@{quCM49>?=eUVdLrI%c5Vfhspnm Wr;i>N%`IgB0000w3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_nW2O zZ5u#5KOR;5bW-v2UYXB_kU4b|T_)qmdtB8}g-G=JaL_;W+`&n@*oK*n7l(){~C z^Y25=e-G6EJ<|I3So7awt$$Cn{y$Lv{}6~Y{yzdD&Hs-z{yzqiTK}JD{s+oF(f;F@2U~D=#C$9oVvwBI8UobG9Ik~uH)YJ{kEUc`Xnp@jDI=g1in}7Vo$x~;~UwQuW z<;z#^KYU`m`AGw)RNT|WF{FYq_X2Y{6N8Au!<^ge%x`bInsa;G**E{*#GT!7{QgH( zf&ZNjDhVlK{)rnkDs+q(tDR?AY+X`VyLF+4r%$!JQ1JA5V3TdM#!`i%OW)r!sB$p!%dGjLwpq|Mb-Dk+ z1cL{kf9~OTmwwF3a9O=H))Y|)8jJaXi1i50`LS-c(BjwW{;st%OM z?pnC*DZ`@q2NUK>1qSWlOoJFh$P)<vrd=TL4e zq4DMmQWl$jRfs6r>rbt8DnKY((vC>TB#QH-3t8tIIr|`B2_9p?UC!#;qNx`DunF(6S5i5 zD*xr*w$K=DzgrJ?l?n^Lmf-%&Qib#ssqmF8Zxzv2O|&)3AtH{sjsFv7jsyJ$cE;aUEGi!>+Kr2%M@7pxd_cK@J%;Kg|BUXA)n7A(5FXu zgc8Rkl5v57WVC}}Jp$cY`07-!?mJp{vqh-zSH^NiDX+HyIw) zvxG$>wE96I)4<=Tf^)A7OFtE2^4%Ofa7l^~o)-DT{`!w6bKu-3gRfr2TOuhF?A5Yp zy;TigtrE^XGA#d6h}n;F@xz_`uD=qF$fswbXS7uDYA)<_bMAw3c&imGAUJj(kiovS z7)w7Cux#(68K9g+etL diff --git a/example/emoticons/heart.png b/example/emoticons/heart.png deleted file mode 100644 index 451058d6d02646eb1b0fac70cde05c02c9864d28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 zcmV-C0>k}@P)xZEyy?R`y=9^UeZv$sUe$-T>!cM1 zkZs(pGk#hUyl8@t?1I~_6oe^S&+{gww`K}`Pun2e|5ghJq1?$-bU1ip+5b#-9XiM417EWeG zqHAlLugifCw6Ze^;286VCy0w(P~asa`g?;X3WA@if~=>o=$g+;gLevmTf)I^9#*Wk zxC`uqMlLBQ_t!)!QpR{(6ug-R&JVOgm!+6w7dQ@nD^NB}2>`F8fakTv@qSiptpo@R z$3Z(DvUIvaGkmSsO7jf(yP)CM&JFdYf!)gfJZNM#fZqxJS6={J%R+Dw5WwsJ0000< KMNUMnLSTaAWev6f diff --git a/example/emoticons/kissing.png b/example/emoticons/kissing.png deleted file mode 100644 index 28d775242312a519611bcf2b29752c4765abb2cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 793 zcmV+!1LpjRP)0YJwXLyT+YM@4acxAkZQJg(eec?~?H$i#GkE*`U-j=O+9c2Md5+I90M-=_ zu0JO^k`&@3;yI$0urr+IvXi(?M89~#a^lqou1UwnH%rj7RRK?v4(@s_x_*=3_vZ_7 z-<4?)+Hl(h!VQFt==$pELby8&2n?7I9A+qO#A=TLz9ub}_9^h`Lpc!I{?lheETQJ+ z3sUAAewK0P(6|}lDGM-d1*WVBPg)QfBXPe0{#GrV2NgK{W+84qFL_qz8!1d9zS{Cm zDFTB=geNR4AsJ!$ACiX0%q;aaX<*+a!_SZNOg|@5#lq7bxjqB_P6N%tOfnYW{1dV{ z4aUrQOqdZGq2+gK;XbOs+^=Q0|FTp;dWu;1%I3F9c&Xt@77{FE5hfYVW70&kG$PQe zhqqRRiCH@>D zzpr~QNyU#3WTN5aTugtGkEsvyQ1?tWzP~da_gs{c`1?xm!9Gva6E23+T$b>IU041B XKE9Q6@a!0~00000NkvXXu0mjf6^?Pr diff --git a/example/emoticons/laughing.png b/example/emoticons/laughing.png deleted file mode 100644 index d65f35ec82967bee26777dbc0deb39f2af387807..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 912 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVEh!|6XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TbxYw3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_nW2O zZ;^bzUH1JhnUA}qKkk$NcvSJzNyX25Wj^nd{d`FN^GTJ@m(;$TQT=*E{_AnYZ^z}o zoly98Qt{gvrEh0czMoR~eqQDKWwoD|ReoMm`+ZgU_cfK@*HwStQ2l*V{r4>(()fK# z^Y?9yKi5_N+)({;DtY|3EcQwEsWV`u|k>&<~M^z(k;4666;Q zOa+`=+%jtF24)sk)=kZ=?H!$6v**n}e&Xb*v*)iofBEv|tM?y1G2Z;70aU8y>Eakt z!I*oYxysm4g7v|TZFA4$FWxry*0$W)8_)iJ^X8hx;rF#Q1~LjSYigEqvtLiX+xsqFON-BS)4DHLo_VU@y|#GmNhMQB z$3+_d&u}_eO=WtJQL7W|(Qx9&zFgJ-Aq6=$>*BTZUkX%K9$)98B-rn^Sn&A4qIx#= zMT_2PwRvfXaK)|Ro$jqDwM_r;iWVlu|36;^Y-L+i`07F8d`0_zJILuOm_Y_pTGa=Le7M z8Ve-lzyNNAhK7cwrlyvbmbSLGuCA`WzP^EhfuW(Hk&%(Hv9XDXiK(fnnVFfnxw(af zg{7sXm6esXwY80njjgS%ot>S%y}g5jgQKIPlarIPiGZ`Sv#YDCo12@vyZfugnPbQo)!S;F^?e$Rl&J?$5$AJ>U2H?cy<3?@tNUTw}y-$S3&ip@LTKlS}pyxv!cS z1tzi`-Y+h`$?;M9-_)P7CKq28t1`4CMjt*jS+ylxpH(tQVr5_DX(=AQd&SNH84^z) z?h^4nxz+TX1ml{GN~t^6$sGE8XD?&#_5Qgwum12SO!y_eg8k>DZ#}}i$96JQ9PXc@ z)x_L+$D~2MGN^J+w?lJf#BTQ{cDWswW~@%wu+%SfQ~UQbs^0hW9t8AUnx@L6aH#aH zxTsF0rM9EgMTzTk%EIpn8Ou&lin}fPF(YJ>>W|#o13J5B^s_Ywl{v25zFJ{%)8T~6 qGetffR?iVh@%psum#XCNA1sd;7O;N0m%t4SM+Q$c}^?_?*vG2_c^dC~e(`tabNsr#&6!`u5 zRNQxE48%8td^h3Y#4$wgS5K$G-EBl**n;4gz)aU>Z1fx9Yt>`5M1@ZuN`&~9V<>hz zq4DMmqL!L}R3e4GnSsTJLR)i)k2n?Cv@6f|pu0rLTX}I~k$ORF*Sr|in zb?}``1V+pVPg_~SGR6vqq~X7%G*d0?1q%H9IM4KRB3ddu?UCza;qNi>EQIX*6B5Ca zSt%BN9vY|R_vqoSR$=kiEZl!tw2+=66~1!dtqfYKiI!&hPry==V1@zT&zNbJCIkiy z@HS|$c2I^NABq>k7p20s@d6csv|L)&wh}&1o54((5gatY*QCLEjtuRuCktVtRA_h6 z%OK4V(=6I7VfcQ^1kenF10-xzlQ0`&AEpT5l2qt$)@cwJH1KjTEs+TU!yCT5j_GuTKMW!u;*rB;j2{qaCfW_zAP1<{?Ju1uouhW zZ&r)t&@3o;OwSS)jneFggiHf}lM2ov8J2%a$JDz?c;J#KAv|sKkNx!@PbR@xEQ7B> z#kmqQ3HIp-EsHkV)bQ0Q;VhJ4<(G8KeUywJ?&N*_m2hm{dM4UN%ayMt!%mfRm&xI+ zQLupEYj>#(_Jf&N{vnNJMUTdTVwQO8?baMVzB>+c-=$;i&rGZzBo1WKbq1DyOvl0( zDHwk%5g*(hvwL&c+`jImy!`k;9GYKF#M~#znEfybjnBm6ds^Z>7e(#fzIJJ_&l63A ii{Wd2wtIu!Oa21oag#O*h5@4h0000YNwYxKE{O{Bq-P~s+`6jn;zB#9=>zo4M zq{98V=gJ@%?vQXI--H4FX(KRW0;WyyPZ{AGH^4KXgS$-)YpD$7pT*;WtAplPtWX$A z{GRb;53Pgh?;t3qMT%JdsM(QE4RP3#Ms2wGKC)(o>c? zc=|MO)+w-(A;N#pM=;@gd|}IIo(x_p7gJ2e7Z^ARCiNQ`()WZO-hK^S4GOGgiO~8< z3=`J#g=QNqdMQIHi6;>-p<9PC^!AakUQWUkjC>c%gbRG3#ag3)hyE*-Bb4w(gckl$ z4Lm(6IICq?NlV7aH!%VFCUP zu?XgjBrN_L&&dj23J1k3Y&^X~H-{gd2*=Fd30T>egw+fpJ&C>(vG`vC=6;RE=;u-R z_K{FQb2vi#dWz2Fzh}eI_(2qAevHBNchRVSGXnomiBDc1eB}0Zhz9!((LmT38{h97 dsllF9_5&MblaH!wQGZEPJXDZ6~N#Mv;!Jef=={5njf1iZ+ zo(u<9hRRMN3}ToVrK`S9g1uM+Z?z7-I)XiG;VIX^m8(SWaS4`w6br8GU?ylhq2lES zLc6jzizw`G(&PRcVt_Uy&}u}W#Q=Y!j=s4Il(3$X;LM*%c=^7N4lX-d7|vL=_n$O) zYqSV78-`>I!w5_oXrzi*OBFC57Gd+})Y9dQFuw4%Po9s2yF>&3U|?9%I)t7;vmX9> zEtRpKlb~~JI^KUQjFaBN7yh#6uT<)4phZ68SfZ9;1Z?b-M-dlqlh^Q?t-$2@fXoSF7MDkimXRgzn9$$oYY0I-4*2ZTAm}G$!71 z6#}(P+Q5@Es0mIMs8PXNqJZm?80G^R=vbA64R1$s!k_uV+dq0L9Oh#}xU*%{9o7mO zukmnaNnkxHK=-CpH2oWo4;~5Sgtv`e*sFJZ83*ez0bG|Q6y#dsE0c4uXE{81GPo{^ z>0i&5RJ1Khz=k)eb*nhX=&h$@+o=1@uL&^k&w%};5YF>r5-`}a2=)^KnD?fmdqWDz zj(!>img%CcH`(E^`0XgPtxG}Q&NTEhLI0j~dhXtsf{qo5sQ)Vt3tkT&bvR6Me7*Zf z7&d+oh3uc>(6%H2tqbFE<(n9+e=`E_JQO;~@iqAY`#mFzVH+fizD;q!&MQ{|T1$wX T^SL{P00000NkvXXu0mjf0kd`( diff --git a/example/emoticons/shocked.png b/example/emoticons/shocked.png deleted file mode 100644 index f3dfb11f8d22ddb7d678befd190322f0df7d330b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 780 zcmV+n1M~ceP)%Z-~r5!eHV=V(9x9l3*TC!ZD$NbDBd<*J|vJC}Hc8W2;hxuO5#D_w8OxurHzV zj!VPVJO0RGqDxMVWnftcEa~80)E+#u_sU_c5uxtAB;0Xv=qeZMDU2Y#&;KwLj!88y zA_+STyI;`2HABN6 zl*8O0!rEVHc;xDEPI{(L_-5YwDKu0S4UL3C!4lms^050wHD#%SV^jfas|4Hm8Tjq- zXioT=P}n_FDuR=Si$zW*6lj@JNMN@HYbh|Iowke zILicV-h{X(#`H$l8=#^od@NCbG{lmY{#lcvS0b8qx4T&;g5*!o6U>mwQ8^*E> zZ2p;y<wT=QzvmpDrKh4Y+NgUg9(r0ib9E-Hjagn9>hn{v@oN&3l|K~)idpAM zFJN={;(;hE|D25N|5CA&PvoW2bqY3qOUCNA37C057N6b|;n^Glx37n2UVeKt3LS66 zV)@H>EPWP-wil!E3k~tX%fkYY&p&wKVeTF3jdDiX^EVMA<@NM@BxVUd&vS9TUq&SzICW!9`=)~;pNuV*u8 zW;SSJG-+is>tMB>%w#i_(QXpE(^L+pSEGI`JE@?OsDyO7IwC9~fmuAsH7LF-t8dxavmvPErYi{8c-vz;ww2V2}O_V^uK zi92|b4{)R(RpW!Ju!&PvWyW|3Q=|!H3t9+H$ zc&o1SR^Q;QxxrU^o3HLRU;Q1vhI{(y#B92i3khQeSdTV~X&i04;&7C&f;rFqut`+9$Q(+~4G{fByb_@!x!VUWZn4 z&MwypDi>GA|L>9vt-Z3mk8_qd%RIGN<=lmPd!p{M9ptLC)Ct`G=j~Mn-BvT@C#s%t zGw(fq7jArEt6Kqsg4v_5OI|U!WP)sma(ylZQFMKv2EM7(e57hms>Y_qh8J8yjQxXT!#TTQ22BG zIsQ8dAWkBlBWei?!)Y!%iQDXm+fSHGy!ya3!8r700(vr3a5fp>sMn+GHyM6^J{I>~ z83fUW+xie5P8>sYef4xK933WX3><;YVTRIXto4}SZqj3^P=!w)ihyX#F&w*FsJr=s zfcb`>6&$=Zek8n8M*-7E15-!CJ9!kg#z@?6f~QpvTZsx~Z^q*0^ZaK;>`q}2@m2ae ziP#u4!#i;lOGri>#V{m2|AcS>jZ_Cqt^z+l&LjPt2$Tv>d*u2McsflqiX%xTk%%;N zB$$aKS-94zhoeG;xnGlT|7C$fdWux|O4?fqJXP-`2kZiqM-oRcBEQjVgsWDA<@6N% z_)wS-z9RmKawHEg6H9*IOEVZ_M7wN?!rB?>J3oPfp`c&8hr!q-w?h~YKa=rO=MMAA`- zWYowAnRn2@LU)Z4maJsVeie%!?hX;cm!-nfAG#_CmI66E4H}-#)&Plz4J={NkO5o$ zdX@=n`7$j0lz{Pfqwv5b0YZ4%&V&8+A5TWYRv?4BR>f1==+t4eTPvWn7HiEKxT}@0 z<)vWpmjq0I6pbJ5Zrx$*V$Ltp|7; diff --git a/example/emoticons/silly.png b/example/emoticons/silly.png deleted file mode 100644 index d4497d9aee01396181aea5545c6fe0dca0109df9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 930 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzVEi566XF`~!14e8e;`Q<6zv2u z7Dz_Ba6;G+TbxYw3l4w}@=$6W=&NVrL2Ofli?Vy`m=?_)fJ8oLVk> zx<%kzx6qYUve!1r-<>RUcdGE+^)mPR1nzB@e>hR_$yC9o(}bSR5PG^u?D-tw=kr8f ztdxAUMD*2Cu~*B)UM&}Yy+Z8GZuz%s#ow-#c)MQm?MCT$8zkOslz6vU>fL7P_ZubN zZRu6+iEh{=8S_^FGRQY^K?aLX}uZLy7 z9+CfgT=Cmcxo^kiznxI{c2e=%8KrM$RKA~5_kYYQTz8m z{of<4e~&f)J<axjH`bc<@hWMQr@qlfRFtst7oT{fXaQUAxoP`o;g{3duU9-ViwP z^JoiGH_s64NKH?|Qx-DngyP!LpG#4!_pVJlrkv&E)?A#z(C`H(RTJcxRbY zd(4MXPQdljG(WxEocw$pzYuCw-AHKZ*8hBkwztDnm{r-UW|D6p}* diff --git a/example/emoticons/sleeping.png b/example/emoticons/sleeping.png deleted file mode 100644 index 2b97a8033ee0907a0600015f7d1c576b6cafb9f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1039 zcmeAS@N?(olHy`uVBq!ia0vp^B0wy~!3-oDVtf1<7?|_|d_r8q9XS5~{|_W-fufy2 z#sbM`7fuKpVvDnhK(-fWjt^IEAa|Z0SH2Hteh5!t5O;An@057%=~;X;3kB!Zi!ILJ zS(3rKB#U=xKHt(p{^ezYtDD8v)C#TZm0aHUlC42`uMGo|eooEm^)h={u zxx(od!E@arS60bg+oW`NvhdxhqIcKJ-Rl#&w_WMsMByh>g`Z9nc{)Sn=^}~eb3~ud z6ML~z`qdJNS4$;cEt7n;T=Mk_$v3-|-maB;yI%V3M%i~8q~C3nez#fn-DbJ>n`Pc_ zk$Jye;r%Z8k2~c)?vnesPwC@PvTidzMWC~c1HdCNu}?nRKA~A|9)BP=UJ7X=T&}Q zR{wcT>-S~V-XUseBoP2=}<&EGdPf8W&leM|fIEuG)Dwf|gI{c~OY&kc<~x3vBM zxp#H`-c|MxWi-v=VC{||sj`~O4j|Brx3=l>(!|BrS4KL(O||DWjo2daFc|Np7p z|EKyJJ56r^6OejIkY6wZ10yFFw~U&)ftiJsbyIU|dq-#2?0NH#pE!By?D;FtU%q_# z>ivgLj5j}N0F`EXx;TbZFy>xho-Q3A(DpDPSNYr8+}mDjuWUPPv@LLV@7en8#mRe* zpFeZaT|r2&FG60SWvyi3%e{<&m(3LzA98dA@G7sX$aIVmp7gsdtzys2g?2@}yN`+I z-}?XOeDllHYjXO_8mxIvYt>zik9w$*$UFZypk`~Lmg2j3jKVY&6{ zH}mil&p*Gke|CNQHUBaOKApcGRA--0-#pXj(d1tzU$*{jNRHO|A7IuTq%qUQ?c>u@ z<%TWF??Tubj|g^IiC+JHj_H%!4k3k)6*^MA7EiA8ZDRQO-FJVt5N~_^%lKHUhKY3^ ze+`+KSZh`tfBrpyQQb_N$KL5-fq}%2Ws~pOY)um>C^-4Hyz2gWhX=dEe}6l-b8$Bt zgY|OrdsA1IlhBw>zi+Dlz6C@Yzi(;&zOC`+y6T@Bs()^&{{gb^0+Ht5n<{^Asrr%D;Q6{~oCSd!YI6k=DP*n*Sba{d=PI|DNjqdusphtNy>Q z_WuD8ssDcnL>m7e0g>ka#~S}114*s_Pc;7n6+hAb|5WS$Q|t;0FJHcT|KStk%}*LYrM8|fjv*C{ zsS`{WU2_m|+dsSK&&LPvEy;hhSz;wA>BX5k#0e<=<8)2dtA*dM*xxpBj_O?P$vm-NJi9X9PTp5}XZ z(c4>b)3U!_zJAQ;c3$?=?`zApHu%?VaF6|8cKGq4h+l>ITW7`Rbsjl)IegN=e2aJM zL?2^L3ucVkf3az_4fVboFyt=akR{0C-T%{{R30 diff --git a/example/emoticons/tongue.png b/example/emoticons/tongue.png deleted file mode 100644 index 73da3e34ba3840435b21ef55c80188ea3841f60c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 981 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqMyzV3H5;32_Z~;Q0UlKaivaigp4S z3nZgmI3a9^EzTwa*yCeLJJ_{iOW&QwrbDt9-w#_Vc{r&&w)5 zuc`gMtn~Y;^6zUZzptzQzM=a2ruy$&K&0{emgeu<8h@@T|GBRE=Z5N^Tk3y++`B-e z`S+IU-@EF6A87u4sQK@X+P}Lh|L&>&d!YXBk=DP*n*Sba{d=PIpNZjrZu44EyIT4g8&ya+rN5k9l3~ z61ORL-psu5sp8<^h1Tuem0gj;7;_=; z=h?bIH&+#dGv(gWx2&ud?0Yi#Z{Ngu`cK~Mo?rj}&yPRo{+)c?|er4V(VBj-&y85}Sb4q9e03`9*5&!@I diff --git a/example/emoticons/unsure.png b/example/emoticons/unsure.png deleted file mode 100644 index 87c7599719d6be5d1766b657921f69e45cedf2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 763 zcmVwym<)wl`SYiq}T8w#~6UZQHhOt6Y^%;h+1?=%qA#$@g+~zUzAdfb$Cd zp1du#-1|{hWxtED204Di|A;=s6(3!7t2tj+E7~`LO;f3jGir@#=+R7foEHe1k7`>uEJo(mdxLhU>m*= z&Z$c%_}J%~CaI-G0d2krdq1R+Ze#@Ug*UwSWGJlN8aO6sWZ-|E^6TA77^@^$*q@9y z9|+>4*YSnlW&DyzQ*}-s6M_N>PkCFv8s>T#Rx?wv`<-x3_%&bHI+ibiolO^~DYOr$ zU}=V(U}EIl`plJjuA4;AGBW6>QxKSn9;k=A>YL zOB{B+8p;X3gv$N}w+kU};YxCV!8{ zTlWQW!W&!<_SQomM?qgCfTdnSi_eY3-YX~go1!mB#qz#H%>EODT`$w002ovPDHLkV1lV$WP<7?rClj>j2XnZ}Q`0a%9x05PAFRTB)s{Z?i=I>kD zf3B<{v+C^3>V$SDwFo`SR8K51$xse$oI% zlBbJfNCji=1?J*rM+ue(-MP0bvu|&EYnJ-vzy00!NpF76l-3pg$|-E<=F+pgPIQB2 z>GKYcD^=+xudb|Ct+*1HCmDOMy83Rc%%&5sHNt*&YE1og(C%q?r=`}RkhNhe4}I@# zaB`R_tG{HQ{*5ILZ+CpiS+_co_rjiAA3vAfi+IBm3U+`=Mk83Ml8`0XfZQHhL+jhq@X$Ie(bLOTQWGCuPe%IeG|3e=D zg9bDgnoGm95?7(ZMF`D4SSutjWeU)DCk1(1qNwnrvrw(e z6vA31V@-mV3Z0H7h3hjFmWyHf$S1;N)b5L>!cJ$QM*EHrONEp+hYF~au#bh&D0f^r z>~&IDO2sg~O-JvIMAYty^bqFP-bi5`ZL5_6RNBbVAajMtY*iBU=L?{Jo`$Xq@yK4w zMmoz`xcSD~Xx1l|G70Q8L|X48sh3ii%w8>lrC0>h`*f)9CZYX!49?C7ros)*!XM@j z4}|)0D$H2|)*M=ey;edboTx?uTcw!DgfM6Fpna5ruJiF|+!cwr|N2wm_wEz>#MNaH z&^}Iq=>v~7iB@7Q6*8!(KUVDM$ oHrO?UOoEOhlY8fVgB?sh0XTn_nkWgd9RL6T07*qoM6N<$f_mL}CIA2c diff --git a/example/emoticons/whistling.png b/example/emoticons/whistling.png deleted file mode 100644 index 3940f0d8215e74f6fb86126b8005e3f95c2eea28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1072 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6I!3-n=6T)m57?^?rd_r8q9XS5~{|_YTiK3lA z)3%2G7!bzNLly%gY3pcgwDB7F$y*w60fjeT(RZKFN&}qz-h79OxB0 z(I9YQg2<_Mp;OBh&b11j>lV4xCwyg<+_i}!*ET8LSSWROz1+R+N{{v{J)SB0c&X&$ z)iO_}3O}78@^q2J(_IQL7E8QXDg9!V#N@P4Pl`(5%McgTL+CHHZk(#HexACD@3+9UVrr0VCr@}Eztf4-#k<)Gr1 zLrP!HXnZ}a`1QE**Rv|$jw*gTru6N&(zlZ;-_EFiJFE8nl*;#Ws^2ebeZQgcR z{C}+b{|ON3|9`3nOiNj_OPhg-%%CL5FPMRWk&}y?S6oI`P2IrE!pb@zv8<`NwWG6Z z_PqHkw;eft;^gVG=dV0}`SR8K51)Sh3aaus0n`)g>Eakt!I+$Igik_3vY}ySxQkSZEI&{(v*_bC(hb$74vq@nPxyi0{>r<1c;=3#BVmACgz{uQOTWu~a;i7)D zHPhip>8bSGd)xEh&$C@E_WjG(GLg27&5cJxmDShW*qeTSU2J!_-t7&kFPG%hI&Rpp zB>nc6UhDF=w>D-Ro0ZERzFW%mMB`Cboo=h;y7#x#{(iHrb90*CMzfw!w(iZRc1+*$ z&3~@_{*_zTZCtv|;&PmXP~M#=yPu)FXV0dJT1sZF{Aadljzgixj+<&}PoAZy9A}yN z@+9|0<<`xe!46J)<}Wrhm~)UpPJfZtu3cV>PJC>VWngH2RKk-Owr3wOk{CQ){an^L HB{Ts5%ZKa> diff --git a/example/emoticons/wink.png b/example/emoticons/wink.png deleted file mode 100644 index 3d1a9cc0725bef494cd960fcff0ad294e44444c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmV+y1L*vTP)*z?q>i6$z6;)!IZ!Aj-g@-LFr>bhh~7*Y9L*Zo8`S9jTY`UHiNnL! zg@V5!#D@t3h!ctK?_Y?Ay;BR%paI?yMo-szto3T)YF1;pNQSQ-j{<+YnF-iWsJ-LT z;DyFNBrJk&!T|rY5tuOn(7YiD6;AP-wQ%OYfkL zLc1jbCg?pwE%f%0uwG8W6pVZp%fbbr&|F9 z$R{y-gl!{fVjk!X;rL$3Hls9ggKDg`DPS*^VDXPcG`$+d!bYL+?X*|pcue5w-IR_A zBx8(*WE%K~)bMmE;i{FvoSlrh@8j_617R$DLnu7w@#{ljE)>JvDCh356#fx4Nj62p zYWN0NrhvOa25W%`i@zse;-hFhdSx&R&)&VTfB5&gXjltHaMj7UODtvJ?NPD_Yb|oP zYNW8{i?H-(0%kss!LRp)vg~_y2!)J}w$WnwTQM-x%-KuCa8^lJ!0A_qAMOAE002ovPDHLkV1k#Le$W5_ diff --git a/example/emoticons/wub.png b/example/emoticons/wub.png deleted file mode 100644 index d5faa2b605b5d4890adb314da8754dd360d5c8f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1010 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz5!3-qlM(p{{z`!IK;1l8+uE6pC|9>D!3ly!u z1vEBFfiqf(J6aLMh9GAFg=_`BY$btQCBa-Zkvs+dJZq%I_Z6M^85I-53#8q;!{6l=6y^^|Cp5dF}v_%PQj=0iqEN8pHs6xXXJj) z%KuzY@+B+(OMc1Mto*Mz1z&RtzvdQx%`5umlkg2l7M6aisQyu0_M^P&M@7|-%IaSg zRlh2#e*qblHNUEAe$~|es;T=`TlcH3{#QK^HT-G-qQ>9VHNR_Wf7jOi2C^HQem6D! zt*`&v(D1jR@o!_(Um&-+`EOg>-;VZwP0jzBfvDwQOUu8uwtpQR|2jMVb#?u3ZTa8Y z`o9f`+Wxn<{qJc1-`VlMs}qE^Zk$bptaCE9<7_*7lCh zuG#bEA3t&O)Y}a<<`Q^X{z3V#8tKV;^zI*8DYq15BCW_8~exJ>DgF92RBg4McxwqqUZ*K#l zZF$$X^~T>=a_z|b!)NXrZZH1S+3}%plktBO?e8s3v(`R+b;qK7wYkw|Uax3X+;aei5s`ykzeTk@1Jb^;>%g4TJKDI%F}i!mH5oD+4r<#sgPhd z!)4pvk9-`udq1abJHJjtgy}#?e0JM()qj(GD^A|{^XuKaTX!(;E(mlhY6&R4bm?dtl|a{u%{|NCv2Gos23oiZL50^^6l)78&q Iol`;+01z+H<^TWy diff --git a/example/example.html b/example/example.html index 378329f31..c158d41db 100644 --- a/example/example.html +++ b/example/example.html @@ -1,91 +1,90 @@ - + - + + SCEditor Demo - + + - + - - + + + + +
-
- +PS: I've not used it and don't have any connection to it.[/quote] + +@[userlink]tha_watcha[/userlink] + +[code=markup]
p { color: red }
[/code] + +[color=#ff00]Red text! [/color][color=#3399ff]Blue?[/color] + +[list][*]A simple list[*]list item 2[/list] +Just type [b]:[/b]) and it should be converted into :) as you typed. -
-
- -
+ + +
+ +
+
+

SCEditor is licensed under the MIT

+
+
- + + - -

SCEditor is licensed under the MIT

+ + + diff --git a/languages/ar.js b/languages/ar.js index 672fe8dff..33260de28 100644 --- a/languages/ar.js +++ b/languages/ar.js @@ -10,8 +10,6 @@ 'Italic': 'مائل', 'Underline': 'خط من الأسفل', 'Strikethrough': 'خط في المنتصف', - 'Subscript': 'حرف منخفض', - 'Superscript': 'حرف مرتفع', 'Align left': 'انحياز إلى اليسار', 'Center': 'توسط', 'Align right': 'انحياز إالى اليمين', @@ -37,8 +35,6 @@ 'Insert a table': 'ادرج جدول', 'Insert a horizontal rule': 'ادرج مسطرة افقية', 'Code': 'كود', - 'Width (optional):': 'عرض (اختياري)', - 'Height (optional):': 'ارتفاع (اختياري)', 'Insert an image': 'ادرج صورة', 'E-mail:': 'بريد الكتروني', 'Insert an email': 'ادرج بريدا الكترونيا', @@ -50,9 +46,6 @@ 'Video URL:': 'وصلة فيديو', 'Insert': 'ادرج', 'Insert a YouTube video': 'ادرج وصلة فيديو يوتيوب', - 'Insert current date': 'ادرج التاريخ الحالي', - 'Insert current time': 'ادرج الوقت الحالي', - 'Print': 'اطبع', 'View source': 'اظهر المصدر', 'Description (optional):': 'الوصف (اختياري)', 'Enter the image URL:': 'ضع وصلة الصورة', diff --git a/languages/ca.js b/languages/ca.js index cf0b09bd2..09d90e80f 100644 --- a/languages/ca.js +++ b/languages/ca.js @@ -10,8 +10,6 @@ 'Italic': 'Cursiva', 'Underline': 'Subratlla', 'Strikethrough': 'Ratllar', - 'Subscript': 'Sub\u00edndice', - 'Superscript': 'Super\u00edndice', 'Align left': 'Alinear a l\'Esquerra', 'Center': 'Centrar', 'Align right': 'Alinear a la dreta', @@ -37,8 +35,6 @@ 'Insert a table': 'Inserir una taula', 'Insert a horizontal rule': 'Insereix una Regla horitzontal', 'Code': 'C\u00f3digo', - 'Width (optional):': 'Ample (Opcional)', - 'Height (optional):': 'Alçada (Opcional)', 'Insert an image': 'Insereix una imatge', 'E-mail:': 'Correu electrònic', 'Insert an email': 'Insereix un Email', @@ -50,9 +46,6 @@ 'Video URL:': 'URL del V\u00eddeo', 'Insert': 'Insereix', 'Insert a YouTube video': 'Insereix un v\u00eddeo de YouTube', - 'Insert current date': 'Insereix data actual', - 'Insert current time': 'Insereix hora actual', - 'Print': 'Imprimir', 'View source': 'Veure C\u00f3digo', 'Description (optional):': 'Descripci\u00f3 (Opcional):', 'Enter the image URL:': 'Ingressar la URL de la imatge:', diff --git a/languages/cn.js b/languages/cn.js index 6a27f0b05..ada633f7a 100644 --- a/languages/cn.js +++ b/languages/cn.js @@ -10,8 +10,6 @@ 'Italic': '斜体', 'Underline': '下划线', 'Strikethrough': '删除线', - 'Subscript': '下标', - 'Superscript': '上标', 'Align left': '靠左对齐', 'Center': '置中', 'Align right': '靠右对齐', @@ -37,8 +35,6 @@ 'Insert a table': '插入表格', 'Insert a horizontal rule': '插入分隔符', 'Code': '代码', - 'Width (optional):': '宽度(选填)', - 'Height (optional):': '高度(选填)', 'Insert an image': '插入图片', 'E-mail:': 'Email地址', 'Insert an email': '插入Email地址', @@ -50,9 +46,6 @@ 'Video URL:': '视频地址', 'Insert': '插入', 'Insert a YouTube video': '插入YouTube视频', - 'Insert current date': '插入当前日期', - 'Insert current time': '插入当前时间', - 'Print': '打印', 'View source': '查看代码', 'Description (optional):': '描述(选填)', 'Enter the image URL:': '输入图片地址', diff --git a/languages/cs.js b/languages/cs.js index c17e1bf97..2465cd9a5 100644 --- a/languages/cs.js +++ b/languages/cs.js @@ -10,8 +10,6 @@ 'Italic': 'Kurzíva', 'Underline': 'Podtržené', 'Strikethrough': 'Přeškrtnuté', - 'Subscript': 'Dolní index', - 'Superscript': 'Horní index', 'Align left': 'Zarovnat vlevo', 'Center': 'Zarovnat na střed', 'Align right': 'Zarovnat vpravo', @@ -37,8 +35,6 @@ 'Insert a table': 'Vložit tabulku', 'Insert a horizontal rule': 'Vložit vodorovnou čáru', 'Code': 'Vložit kód', - 'Width (optional):': 'Šířka (volitelné)', - 'Height (optional):': 'Výška (volitelné)', 'Insert an image': 'Vložit obrázek', 'E-mail:': 'E-mailová adresa', 'Insert an email': 'Vložit e-mail', @@ -50,9 +46,6 @@ 'Video URL:': 'Adresa videa', 'Insert': 'Vložit', 'Insert a YouTube video': 'Vložte video z YouTube', - 'Insert current date': 'Vložte aktuální datum', - 'Insert current time': 'Vložte aktuální čas', - 'Print': 'Vytisknout', 'View source': 'Zobrazit zdroj', 'Description (optional):': 'Popis (volitelné)', 'Enter the image URL:': 'Vložte adresu obrázku', @@ -64,7 +57,6 @@ 'Invalid YouTube video': 'Neplatné YouTube video', 'Add indent': 'Posunout na další úroveň', 'Remove one indent': 'Posunout na předchozí úroveň', - 'Maximize': 'Zobrazit přes celou obrazovku', dateFormat: 'day-month-year' }; diff --git a/languages/de.js b/languages/de.js index da29c0475..aa42a03ed 100644 --- a/languages/de.js +++ b/languages/de.js @@ -6,8 +6,6 @@ 'Italic': 'Kursiv', 'Underline': 'Unterstrichen', 'Strikethrough': 'Durchgestrichen', - 'Subscript': 'Tiefgestellt', - 'Superscript': 'Hochgestellt', 'Align left': 'Linksbündig ausrichten', 'Center': 'Zentrieren', 'Align right': 'Rechtsbündig ausrichten', @@ -36,8 +34,6 @@ 'Insert a horizontal rule': 'Horizontale Linie einfügen', 'Code': 'Code', 'Insert a Quote': 'Zitat einfügen', - 'Width (optional):': 'Breite (Optional)', - 'Height (optional):': 'Höhe (Optional)', 'Insert an image': 'Ein Bild einfügen', 'E-mail:': 'E-Mail', 'Insert an email': 'E-Mail einfügen', @@ -45,16 +41,10 @@ 'Insert a link': 'Link einfügen', 'Unlink': 'Link entfernen', 'More': 'Mehr', - 'Left-to-Right': 'Links nach rechts', - 'Right-to-Left': 'Rechts nach links', 'Insert an emoticon': 'Emoticon einfügen', 'Video URL:': 'Video URL', 'Insert': 'Einfügen', 'Insert a YouTube video': 'YouTube Video einfügen', - 'Insert current date': 'Aktuelles Datum einfügen', - 'Insert current time': 'Aktuelle Uhrzeit einfügen', - 'Print': 'Drucken', - 'Maximize': 'Maximieren', 'View source': 'Quelltext ansehen', dateFormat: 'day.month.year' }; diff --git a/languages/el.js b/languages/el.js index 05d33ecc0..d46a74541 100644 --- a/languages/el.js +++ b/languages/el.js @@ -9,8 +9,6 @@ 'Italic': 'Πλάγια', 'Underline': 'Υπογραμμισμένα', 'Strikethrough': 'Διαγραμμισμένα', - 'Subscript': 'Δείκτης', - 'Superscript': 'Εκθέτης', 'Align left': 'Αριστερή στοίχιση', 'Center': 'Κεντραρισμένα', 'Align right': 'Δεξιά στοίχιση', @@ -36,8 +34,6 @@ 'Insert a table': 'Εισαγωγή πίνακα', 'Insert a horizontal rule': 'Εισαγωγή οριζόντιας γραμμής', 'Code': 'Κώδικας', - 'Width (optional):': 'Πλάτος (Προαιρετικό)', - 'Height (optional):': 'Ύψος (Προαιρετικό)', 'Insert an image': 'Εισαγωγή εικόνας', 'E-mail:': 'Ηλεκτρονικό ταχυδρομείο', 'Insert an email': 'Εισαγωγή email', @@ -49,10 +45,6 @@ 'Video URL:': 'Διεύθυνση βίντεο', 'Insert': 'Εισαγωγή', 'Insert a YouTube video': 'Εισαγωγή βίντεο YouTube', - 'Insert current date': 'Εισαγωγή τρέχουσας ημερομηνίας', - 'Insert current time': 'Εισαγωγή τρέχουσας ώρας', - 'Print': 'Εκτύπωση', - 'Maximize': 'Μεγιστοποίηση', 'View source': 'Προβολή πηγαίου κώδικα', 'Description (optional):': 'Περιγραφή (προαιρετικό)', 'Enter the image URL:': 'Εισάγετε τη διεύθυνση εικόνας', diff --git a/languages/es.js b/languages/es.js index aece0ab9e..55a79ed12 100644 --- a/languages/es.js +++ b/languages/es.js @@ -10,8 +10,6 @@ 'Italic': 'Cursiva', 'Underline': 'Subrayar', 'Strikethrough': 'Tachar', - 'Subscript': 'Sub\u00edndice', - 'Superscript': 'Super\u00edndice', 'Align left': 'Alinear a la Izquierda', 'Center': 'Centrar', 'Align right': 'Alinear a la Derecha', @@ -37,8 +35,6 @@ 'Insert a table': 'Insertar una Tabla', 'Insert a horizontal rule': 'Insertar una Regla Horizontal', 'Code': 'C\u00f3digo', - 'Width (optional):': 'Ancho (Opcional)', - 'Height (optional):': 'Altura (Opcional)', 'Insert an image': 'Insertar una Imagen', 'E-mail:': 'E-mail', 'Insert an email': 'Insertar un Email', @@ -50,9 +46,6 @@ 'Video URL:': 'URL del V\u00eddeo', 'Insert': 'Insertar', 'Insert a YouTube video': 'Insertar un v\u00eddeo de YouTube', - 'Insert current date': 'Insertar fecha actual', - 'Insert current time': 'Insertar hora actual', - 'Print': 'Imprimir', 'View source': 'Ver C\u00f3digo', 'Description (optional):': 'Descripci\u00f3n (Opcional):', 'Enter the image URL:': 'Ingresar la URL de la imagen:', diff --git a/languages/et.js b/languages/et.js index 3c789b22f..efd8a41f5 100644 --- a/languages/et.js +++ b/languages/et.js @@ -6,8 +6,6 @@ 'Italic': 'Kaldkiri', 'Underline': 'Allajoonitud', 'Strikethrough': 'Läbijoonitud', - 'Subscript': 'Allindeks', - 'Superscript': 'Ülaindeks', 'Align left': 'Joonad vasakule', 'Center': 'Joonda keskele', 'Align right': 'Joonda paremale', @@ -34,8 +32,6 @@ 'Insert a horizontal rule': 'Sisesta horisontaalne joon', 'Code': 'Kood', 'Insert a Quote': 'Sisesta tsitaat', - 'Width (optional):': 'Laius (Valikuline)', - 'Height (optional):': 'Kõrgus (Valikuline)', 'Insert an image': 'Sisesta pilt', 'E-mail:': 'E-post', 'Insert an email': 'Sisesta e-posti aadress', @@ -47,9 +43,6 @@ 'Video URL:': 'Video link', 'Insert': 'Sisesta', 'Insert a YouTube video': 'Sisesta YouTube video', - 'Insert current date': 'Sisesta praegune kuupäev', - 'Insert current time': 'Sisesta praegune kellaaeg', - 'Print': 'Prindi', 'View source': 'Vaata lähtekoodi', dateFormat: 'day.month.year' diff --git a/languages/fa.js b/languages/fa.js index 0c2c02d96..c82765a4b 100644 --- a/languages/fa.js +++ b/languages/fa.js @@ -9,8 +9,6 @@ 'Italic': 'مورب', 'Underline': 'زیرخط', 'Strikethrough': 'خط خورده', - 'Subscript': 'زیرنویس', - 'Superscript': 'بالانویس', 'Align left': 'چپ چین', 'Center': 'وسط چین', 'Align right': 'راست چین', @@ -37,8 +35,6 @@ 'Insert a horizontal rule': 'افزودن خط افقی', 'Code': 'کد', 'Insert a Quote': 'افزودن نقل قول', - 'Width (optional):': 'پهنا (دلخواه):', - 'Height (optional):': 'ارتفاع (دلخواه):', 'Insert an image': 'افزودن عکس', 'E-mail:': 'ایمیل', 'Insert an email': 'افزودن ایمیل', @@ -50,9 +46,6 @@ 'Video URL:': 'آدرس اینترنتی ویدیو', 'Insert': 'افزودن', 'Insert a YouTube video': 'افزودن فیلم از یوتوب', - 'Insert current date': 'افزودن تاریخ اکنون', - 'Insert current time': 'افزودن زمان اکنون', - 'Print': 'چاپ', 'View source': 'مشاهده سورس', 'Description (optional):': 'توضیحات (دلخواه):', 'Enter the image URL:': 'آدرس اینترنتی عکس را وارد کنید:', @@ -61,8 +54,6 @@ 'Enter URL:': 'آدرس اینترنتی را وارد کنید:', 'Enter the YouTube video URL or ID:': 'آدرس اینترنتی فیلم یوتوب یا شناسه ویدیو را وارد کنید:', 'Invalid YouTube video': 'فیلم یوتوب غیر معتبر است', - 'Right-to-Left': 'راست به چپ', - 'Left-to-Right': 'چپ به راست', dateFormat: 'year.month.day' }; diff --git a/languages/fi.js b/languages/fi.js index e68a4a8ee..adae2b75d 100644 --- a/languages/fi.js +++ b/languages/fi.js @@ -11,8 +11,6 @@ 'Italic': 'Kursivoitu', 'Underline': 'Alleviivattu', 'Strikethrough': 'Yliviivattu', - 'Subscript': 'Alaindeksi', - 'Superscript': 'Yläindeksi', 'Align left': 'Tasaa Vasemmalle', 'Center': 'Tasaa Keskelle', 'Align right': 'Tasaa Oikealle', @@ -38,8 +36,6 @@ 'Insert a table': 'Lisää taulukko', 'Insert a horizontal rule': 'Lisää vaakasuuntainen sääntö', 'Code': 'Koodi', - 'Width (optional):': 'Leveys (valinnainen):', - 'Height (optional):': 'Korkeus (valinnainen):', 'Insert an image': 'Lisää kuva', 'E-mail:': 'Sähköpostiosoite:', 'Insert an email': 'Syötä sähköpostiosoite', @@ -51,9 +47,6 @@ 'Video URL:': 'Videon osoite:', 'Insert': 'Lisää', 'Insert a YouTube video': 'Lisää YouTube-video', - 'Insert current date': 'Lisää nykyinen päivämäärä', - 'Insert current time': 'Lisää nykyinen aika', - 'Print': 'Tulosta', 'View source': 'Näytä lähdekoodi', 'Description (optional):': 'Kuvaus (valinnainen):', 'Enter the image URL:': 'Syötä kuvan URL-osoite:', diff --git a/languages/fr.js b/languages/fr.js index 9c98a89ed..d0f2948b7 100644 --- a/languages/fr.js +++ b/languages/fr.js @@ -9,8 +9,6 @@ 'Italic': 'Italique', 'Underline': 'Souligné', 'Strikethrough': 'Barré', - 'Subscript': 'Indice', - 'Superscript': 'Exposant', 'Align left': 'Aligner à gauche', 'Center': 'Centrer', 'Align right': 'Aligner à droite', @@ -37,8 +35,6 @@ 'Insert a horizontal rule': 'Insérer une ligne horizontale', 'Code': 'Code', 'Insert a Quote': 'Insérer une citation', - 'Width (optional):': 'Largeur (Optionnelle)', - 'Height (optional):': 'Hauteur (Optionnelle)', 'Insert an image': 'Insérer une image', 'E-mail:': 'Courriel', 'Insert an email': 'Insérer un courriel', @@ -50,9 +46,6 @@ 'Video URL:': 'URL Vidéo', 'Insert': 'Insérer', 'Insert a YouTube video': 'Insérer une vidéo YouTube', - 'Insert current date': 'Insérer la date actuelle', - 'Insert current time': 'Insérer l\'heure actuelle', - 'Print': 'Imprimer', 'View source': 'Afficher le texte brut', 'Description (optional):': 'Description (Optionnelle)', 'Enter the image URL:': 'Entrez l\'URL de l\'image:', @@ -61,8 +54,6 @@ 'Enter URL:': 'Entrez une URL:', 'Enter the YouTube video URL or ID:': 'Entrez l\'URL ou l\'ID de la vidéo YouTube:', 'Invalid YouTube video': 'Vidéo YouTube invalide', - 'Right-to-Left': 'De droite à gauche', - 'Left-to-Right': 'De gauche à droite', dateFormat: 'day/month/year' }; diff --git a/languages/gl.js b/languages/gl.js index ec6e1a9ee..ed7ab0493 100644 --- a/languages/gl.js +++ b/languages/gl.js @@ -10,8 +10,6 @@ 'Italic': 'Cursiva', 'Underline': 'Subrayar', 'Strikethrough': 'Riscar', - 'Subscript': 'Sub\u00edndice', - 'Superscript': 'Super\u00edndice', 'Align left': 'Alinear á Esquerda', 'Center': 'Centrar', 'Align right': 'Alinear á Dereita', @@ -37,8 +35,6 @@ 'Insert a table': 'Engadir unha Tabla', 'Insert a horizontal rule': 'Engadir unha Regla Horizontal', 'Code': 'C\u00f3digo', - 'Width (optional):': 'Ancho (Opcional)', - 'Height (optional):': 'Altura (Opcional)', 'Insert an image': 'Engadir unha Imaxen', 'E-mail:': 'E-mail', 'Insert an email': 'Engadir un Email', @@ -50,9 +46,6 @@ 'Video URL:': 'URL do V\u00eddeo', 'Insert': 'Engadir', 'Insert a YouTube video': 'Engadir un v\u00eddeo de YouTube', - 'Insert current date': 'Engadir data actual', - 'Insert current time': 'Engadir hora actual', - 'Print': 'Imprimir', 'View source': 'Ver C\u00f3digo', 'Description (optional):': 'Descripci\u00f3n (Opcional):', 'Enter the image URL:': 'Ingresar a URL da imaxen:', diff --git a/languages/hu.js b/languages/hu.js index 0fd64a356..0723566d4 100644 --- a/languages/hu.js +++ b/languages/hu.js @@ -11,8 +11,6 @@ 'Italic': 'Dőlt', 'Underline': 'Aláhúzva', 'Strikethrough': 'Áthúzva', - 'Subscript': 'Alsó index', - 'Superscript': 'Felső index', 'Align left': 'Balra zárt', 'Center': 'Középre zárt', 'Align right': 'Jobbra zárt', @@ -38,8 +36,6 @@ 'Insert a table': 'Táblázat beszúrása', 'Insert a horizontal rule': 'Vízszintes vonal beszúrása', 'Code': 'Kód', - 'Width (optional):': 'Szélesség (nem kötelező):', - 'Height (optional):': 'Magasság (nem kötelező):', 'Insert an image': 'Illessz be egy képet', 'E-mail:': 'Email:', 'Insert an email': 'Illessz be egy email címet.', @@ -51,9 +47,6 @@ 'Video URL:': 'Video link:', 'Insert': 'Beszúrás', 'Insert a YouTube video': 'Youtube video beszúrása', - 'Insert current date': 'Szúrd be az aktuális dátumot', - 'Insert current time': 'Szúrd be a jelenlegi időt', - 'Print': 'Nyomtatás', 'View source': 'Forrás', 'Description (optional):': 'Hivatkozás szövege (nem kötelező)', 'Enter the image URL:': 'Kép URL beillesztése:', diff --git a/languages/id.js b/languages/id.js index 3ee7783d2..edfe6337f 100644 --- a/languages/id.js +++ b/languages/id.js @@ -10,8 +10,6 @@ 'Italic': 'Miring', 'Underline': 'Garis Bawah', 'Strikethrough': 'Coret', - 'Subscript': 'Tulisan dibawah garis', - 'Superscript': 'Tulisan diatas garis', 'Align left': 'Rata Kiri', 'Center': 'Rata Tengah', 'Align right': 'Rata Kanan', @@ -37,8 +35,6 @@ 'Insert a table': 'Sisipkan sebuah tabel', 'Insert a horizontal rule': 'Sisipkan aturan horisontal', 'Code': 'Kode', - 'Width (optional):': 'Lebar (opsional)', - 'Height (optional):': 'Tinggi (opsional)', 'Insert an image': 'Sisipkan Gambar', 'E-mail:': 'Surel', 'Insert an email': 'Sisipkan surel', @@ -50,9 +46,6 @@ 'Video URL:': 'URL Video', 'Insert': 'Sisipkan', 'Insert a YouTube video': 'Sisipkan video Youtube', - 'Insert current date': 'Sisipkan tanggal sekarang', - 'Insert current time': 'Sisipkan waktu sekarang', - 'Print': 'Print', 'View source': 'Lihat sumber', 'Description (optional):': 'Deskripsi (opsional)', 'Enter the image URL:': 'Masukkan URL gambar', diff --git a/languages/it.js b/languages/it.js index b37fcc436..68e9b9279 100644 --- a/languages/it.js +++ b/languages/it.js @@ -11,8 +11,6 @@ 'Italic': 'Corsivo', 'Underline': 'Sottolineato', 'Strikethrough': 'Barrato', - 'Subscript': 'Pedice', - 'Superscript': 'Apice', 'Align left': 'Allinea a sinistra', 'Center': 'Centrato', 'Align right': 'Allinea a destra', @@ -38,8 +36,6 @@ 'Insert a table': 'Inserisci una tabella', 'Insert a horizontal rule': 'Inserisci riga orizzontale', 'Code': 'Codice', - 'Width (optional):': 'Larghezza(opzionale):', - 'Height (optional):': 'Altezza(opzionale):', 'Insert an image': 'Inserisci un\'immagine', 'E-mail:': 'E-mail:', 'Insert an email': 'Inserisci una email', @@ -51,9 +47,6 @@ 'Video URL:': 'URL del video', 'Insert': 'Inserisci', 'Insert a YouTube video': 'Inserisci un video YouTube', - 'Insert current date': 'Inserisci data corrente', - 'Insert current time': 'Inserisci ora corrente', - 'Print': 'Stampa', 'View source': 'Vedi codice sorgente', 'Description (optional):': 'Descrizione (opzionale):', 'Enter the image URL:': 'Inserisci URL dell\'immagine', diff --git a/languages/ja.js b/languages/ja.js index c036d6eec..c87a11506 100644 --- a/languages/ja.js +++ b/languages/ja.js @@ -10,8 +10,6 @@ 'Italic': '斜字', 'Underline': '下線', 'Strikethrough': '取り消し線', - 'Subscript': '下付き文字', - 'Superscript': '上付き文字', 'Align left': '左揃え', 'Center': '中央揃え', 'Align right': '右揃え', @@ -37,8 +35,6 @@ 'Insert a table': '表を挿入', 'Insert a horizontal rule': '水平線を挿入', 'Code': 'コード', - 'Width (optional):': '幅 (オプション)', - 'Height (optional):': '高さ (オプション)', 'Insert an image': '画像を挿入', 'E-mail:': 'メールアドレス', 'Insert an email': 'メールアドレスを挿入', @@ -50,9 +46,6 @@ 'Video URL:': '動画URL', 'Insert': '挿入', 'Insert a YouTube video': 'Youtubeを挿入', - 'Insert current date': '現在の日付を挿入', - 'Insert current time': '現在の時間を挿入', - 'Print': '印刷', 'View source': 'ソースを表示', 'Description (optional):': '説明 (オプション)', 'Enter the image URL:': '画像URLを入力してください。', @@ -62,8 +55,6 @@ 'Enter the YouTube video URL or ID:': 'Youtubeの動画URLまたはIDを入力してください。', 'Insert a Quote': '引用を挿入', 'Invalid YouTube video': '不正なYoutube動画', - 'Left-to-Right': '左から右へ', - 'Right-to-Left': '右から左へ', 'Maximize': '最大化', dateFormat: 'year-month-day' diff --git a/languages/lt.js b/languages/lt.js index 708e83f26..2190d4914 100644 --- a/languages/lt.js +++ b/languages/lt.js @@ -10,8 +10,6 @@ 'Italic': 'Pasvirasis', 'Underline': 'Pabraukti', 'Strikethrough': 'Perbraukti', - 'Subscript': 'Parašyti sumažintas raides po žodžio', - 'Superscript': 'Parašyti sumažintas raides virš žodžio', 'Align left': 'Kairysis lygiavimas', 'Center': 'Centrinis lygiavimas', 'Align right': 'Dešinysis lygiavimas', @@ -37,8 +35,6 @@ 'Insert a table': 'Įterpti lentelę', 'Insert a horizontal rule': 'Įterpti horizontalią liniją', 'Code': 'Šalies kodas', - 'Width (optional):': 'plotis (laisvai pasirenkamas)', - 'Height (optional):': 'aukštis (laisvai pasirenkamas)', 'Insert an image': 'Įterpti nuotrauką', 'E-mail:': 'Elektroninis paštas', 'Insert an email': 'Įterpti elktroninio pašto nuorodą', @@ -50,9 +46,6 @@ 'Video URL:': 'Vaizdo klipo nuoroda', 'Insert': 'Įterpti', 'Insert a YouTube video': 'Įterpti Youtube vaizdo klipą', - 'Insert current date': 'Įterpti esamą datą (diena-mėnuo-metai)', - 'Insert current time': 'Įterpti esamą laiką', - 'Print': 'Atspausdinti', 'View source': 'Peržiūrėti šaltinį', 'Description (optional):': 'Aprašymas (laisvai pasirenkamas)', 'Enter the image URL:': 'Įterpti nuotraukos adresą', diff --git a/languages/nb.js b/languages/nb.js index f58fda754..c1d7b16ac 100644 --- a/languages/nb.js +++ b/languages/nb.js @@ -10,8 +10,6 @@ 'Italic': 'Kursiv', 'Underline': 'Understrek', 'Strikethrough': 'Gjennomstrek', - 'Subscript': 'Senket', - 'Superscript': 'Hevet', 'Align left': 'Sidestill til venstre', 'Center': 'Midstill', 'Align right': 'Sidestill til høyre', @@ -37,8 +35,6 @@ 'Insert a table': 'Sett inn en tabell', 'Insert a horizontal rule': 'Sett en horisontal regel', 'Code': 'Kode', - 'Width (optional):': 'Bredde (valgfritt):', - 'Height (optional):': 'Høyde (valgfritt):', 'Insert an image': 'Sett inn et bilde', 'E-mail:': 'E-post', 'Insert an email': 'Sett inn en e-post', @@ -50,9 +46,6 @@ 'Video URL:': 'Video URL', 'Insert': 'Sett inn', 'Insert a YouTube video': 'Sett inn en YouTube-video', - 'Insert current date': 'Sett inn gjeldende dato', - 'Insert current time': 'Sett inn gjeldende klokkeslett', - 'Print': 'Skriv ut', 'View source': 'Vis kildekode', 'Description (optional):': 'Beskrivelse (valgfritt):', 'Enter the image URL:': 'Skriv inn bildet\'s URL:', diff --git a/languages/nl.js b/languages/nl.js index b56c147c1..817b5867e 100644 --- a/languages/nl.js +++ b/languages/nl.js @@ -11,8 +11,6 @@ 'Italic': 'Cursief', 'Underline': 'Onderlijnd', 'Strikethrough': 'Doorhalen', - 'Subscript': 'Subscript', - 'Superscript': 'Superscript', 'Align left': 'Links uitlijnen', 'Center': 'Centreren', 'Align right': 'Rechts uitlijnen', @@ -38,8 +36,6 @@ 'Insert a table': 'Tabel', 'Insert a horizontal rule': 'Horizontale regel invoegen', 'Code': 'Code', - 'Width (optional):': 'Breedte (optioneel):', - 'Height (optional):': 'Hoogte (optioneel):', 'Insert an image': 'Afbeelding invoegen', 'E-mail:': 'E-mail', 'Insert an email': 'E-mail invoegen', @@ -51,9 +47,6 @@ 'Video URL:': 'Video URL', 'Insert': 'Invoegen', 'Insert a YouTube video': 'YouTube video invoegen', - 'Insert current date': 'Huidige datum invoegen', - 'Insert current time': 'Huidige tijd invoegen', - 'Print': 'Print', 'View source': 'Bron bekijken', 'Description (optional):': 'Beschrijving (optioneel):', 'Enter the image URL:': 'Voer de afbeelding URL in:', diff --git a/languages/pl.js b/languages/pl.js index dabba366f..ecc6f2d97 100644 --- a/languages/pl.js +++ b/languages/pl.js @@ -10,8 +10,6 @@ 'Italic': 'Kursywa', 'Underline': 'Podkreślenie', 'Strikethrough': 'Przekreślenie', - 'Subscript': 'Indeks dolny', - 'Superscript': 'Indeks górny', 'Align left': 'Do lewej', 'Center': 'Do środka', 'Align right': 'Do prawej', @@ -37,8 +35,6 @@ 'Insert a table': 'Wstaw tabelę', 'Insert a horizontal rule': 'Wstaw linię poziomą', 'Code': 'Kod', - 'Width (optional):': 'Szerokość (opcjonalnie)', - 'Height (optional):': 'Wysokość (opcjonalnie)', 'Insert an image': 'Wstaw obrazek', 'E-mail:': 'E-mail', 'Insert an email': 'Wstaw e-mail', @@ -50,9 +46,6 @@ 'Video URL:': 'URL do filmu', 'Insert': 'Wstaw', 'Insert a YouTube video': 'Wstaw film YouTube', - 'Insert current date': 'Wstaw aktualną datę', - 'Insert current time': 'Wstaw aktualny czas', - 'Print': 'Drukuj', 'View source': 'Pokaż źródło', 'Description (optional):': 'Opis (opcjonalny)', 'Enter the image URL:': 'Wstaw URL do obrazka', diff --git a/languages/pt-BR.js b/languages/pt-BR.js index f21f134ef..89b24dc91 100644 --- a/languages/pt-BR.js +++ b/languages/pt-BR.js @@ -10,8 +10,6 @@ 'Italic': 'Itálico', 'Underline': 'Sublinhado', 'Strikethrough': 'Rasurado', - 'Subscript': 'Subscrito', - 'Superscript': 'Sobrescrito ', 'Align left': 'Alinhar à esquerda', 'Center': 'Centralizar', 'Align right': 'Alinhar à direita', @@ -37,8 +35,6 @@ 'Insert a table': 'Inserir uma tabela', 'Insert a horizontal rule': 'Inserir uma linha horizontal', 'Code': 'Código', - 'Width (optional):': 'Largura (opcional):', - 'Height (optional):': 'Altura (opcional):', 'Insert an image': 'Inserir uma imagem', 'E-mail:': 'E-mail:', 'Insert an email': 'Inserir um e-mail', @@ -50,9 +46,6 @@ 'Video URL:': 'Video URL:', 'Insert': 'Inserir', 'Insert a YouTube video': 'Inserir YouTube video', - 'Insert current date': 'Inserir a data atual', - 'Insert current time': 'Inserir a hora atual', - 'Print': 'Imprimir', 'View source': 'Fonte', 'Description (optional):': 'Descrição (opcional):', 'Enter the image URL:': 'Informe o endereço URL da imagem:', diff --git a/languages/pt.js b/languages/pt.js index d8545150a..55470408f 100644 --- a/languages/pt.js +++ b/languages/pt.js @@ -10,8 +10,6 @@ 'Italic': 'Itálico', 'Underline': 'Sublinhado', 'Strikethrough': 'Rasurado', - 'Subscript': 'Subscrito', - 'Superscript': 'Sobrescrito ', 'Align left': 'Alinhar à esquerda', 'Center': 'Centrar', 'Align right': 'Alinhar à direita', @@ -37,8 +35,6 @@ 'Insert a table': 'Inserir uma tabela', 'Insert a horizontal rule': 'Inserir uma linha horizontal', 'Code': 'Código', - 'Width (optional):': 'Largura (opcional):', - 'Height (optional):': 'Altura (opcional):', 'Insert an image': 'Inserir uma imagem', 'E-mail:': 'E-mail:', 'Insert an email': 'Inserir um e-mail', @@ -50,9 +46,6 @@ 'Video URL:': 'Video URL:', 'Insert': 'Inserir', 'Insert a YouTube video': 'Inserir YouTube video', - 'Insert current date': 'Inserir a data atual', - 'Insert current time': 'Inserir a hora atual', - 'Print': 'Imprimir', 'View source': 'Código fonte', 'Description (optional):': 'Descrição (opcional):', 'Enter the image URL:': 'Introduza o endereço URL da imagem:', diff --git a/languages/ru.js b/languages/ru.js index fced0e9d1..dac4f6cd6 100644 --- a/languages/ru.js +++ b/languages/ru.js @@ -6,8 +6,6 @@ 'Italic': 'Курсив', 'Underline': 'Подчёркнутый', 'Strikethrough': 'Зачёркнутый', - 'Subscript': 'Нижний индекс', - 'Superscript': 'Верхний индекс', 'Align left': 'Выравнивание по левому краю', 'Center': 'Выравнивание по центру', 'Align right': 'Выравнивание по правому краю', @@ -34,8 +32,6 @@ 'Insert a horizontal rule': 'Горизонтальная линия', 'Code': 'Код', 'Insert a Quote': 'Цитата', - 'Width (optional):': 'Ширина (необязательно):', - 'Height (optional):': 'Высота (необязательно):', 'Insert an image': 'Изображение', 'E-mail:': 'E-mail', 'Insert an email': 'E-mail', @@ -47,13 +43,8 @@ 'Video URL:': 'Видео URL', 'Insert': 'Вставить', 'Insert a YouTube video': 'YouTube-видео', - 'Insert current date': 'Текущая дата', - 'Insert current time': 'Текущее время', - 'Print': 'Распечатать', 'View source': 'Показать код', 'Maximize': 'Развернуть', - 'Left-to-Right': 'Слева направо', - 'Right-to-Left': 'Справа налево', 'Description (optional):': 'Описание (необязательно):', dateFormat: 'day.month.year' }; diff --git a/languages/sk.js b/languages/sk.js index 84a02c461..862d2e5d6 100644 --- a/languages/sk.js +++ b/languages/sk.js @@ -9,8 +9,6 @@ 'Italic': 'Kurzíva', 'Underline': 'Podčiarknuté', 'Strikethrough': 'Prečiarknuté', - 'Subscript': 'Dolný index', - 'Superscript': 'Horný index', 'Align left': 'Zarovnať vľavo', 'Center': 'Zarovnať na stred', 'Align right': 'Zarovnať vpravo', @@ -36,8 +34,6 @@ 'Insert a table': 'Vložiť tabuľku', 'Insert a horizontal rule': 'Vložiť vodorovnú čiaru', 'Code': 'Vložiť kód', - 'Width (optional):': 'Šírka (voliteľné):', - 'Height (optional):': 'Výška (voliteľné):', 'Insert an image': 'Vložiť obrázok', 'E-mail:': 'E-mail:', 'Insert an email': 'Vložiť E-mail', @@ -49,9 +45,6 @@ 'Video URL:': 'URL adresa videa:', 'Insert': 'Vložiť', 'Insert a YouTube video': 'Vložiť YouTube video', - 'Insert current date': 'Vložiť dnešný dátum', - 'Insert current time': 'Vložiť aktuálny čas', - 'Print': 'Vytlačiť', 'View source': 'Zobraziť zdrojový kód', 'Description (optional):': 'Popis (voliteľné):', 'Enter the image URL:': 'Vložte URL adresu obrázka:', @@ -61,8 +54,6 @@ 'Enter the YouTube video URL or ID:': 'Vložte URL adresu YouTube videa alebo jeho ID:', 'Insert a Quote': 'Vložiť citát', 'Invalid YouTube video': 'Neplatné YouTube video', - 'Left-to-Right': 'Zľava doprava', - 'Right-to-Left': 'Zprava doľava', 'Drop files here': 'Presuňte súbory sem', 'Maximize': 'Maximalizovať', dateFormat: 'day. month. year' diff --git a/languages/sv.js b/languages/sv.js index eae04422b..e767b790d 100644 --- a/languages/sv.js +++ b/languages/sv.js @@ -6,8 +6,6 @@ 'Italic': 'Kursiv', 'Underline': 'Understruken', 'Strikethrough': 'Genomstruken', - 'Subscript': 'Nersänkt', - 'Superscript': 'Upphöjt', 'Align left': 'Vänsterställ', 'Center': 'Centrera', 'Align right': 'Högerställ', @@ -33,8 +31,6 @@ 'Insert a table': 'Infoga tabell', 'Insert a horizontal rule': 'Infoga skiljestreck', 'Code': 'Kod', - 'Width (optional):': 'Bredd (valfritt):', - 'Height (optional):': 'Höjd (valfritt):', 'Insert an image': 'Infoga bild', 'E-mail:': 'E-post', 'Insert an email': 'Infoga e-post', @@ -46,9 +42,6 @@ 'Video URL:': 'Video URL', 'Insert': 'Infoga', 'Insert a YouTube video': 'Infoga YouTube-video', - 'Insert current date': 'Infoga dagens datum', - 'Insert current time': 'Infoga nuvarande tid', - 'Print': 'Skriv ut', 'View source': 'Visa källkod', 'Description (optional):': 'Beskrivning (valfritt):', dateFormat: 'year-month-day' diff --git a/languages/template.js b/languages/template.js index 354970f18..8a9bad5cd 100644 --- a/languages/template.js +++ b/languages/template.js @@ -14,8 +14,7 @@ 'Italic': '', 'Underline': '', 'Strikethrough': '', - 'Subscript': '', - 'Superscript': '', + 'Highlight': '', 'Align left': '', 'Center': '', 'Align right': '', @@ -43,8 +42,6 @@ 'Insert a table': '', 'Insert a horizontal rule': '', 'Code': '', - 'Width (optional):': '', - 'Height (optional):': '', 'Insert an image': '', 'E-mail:': '', 'Insert an email': '', @@ -56,9 +53,6 @@ 'Video URL:': '', 'Insert': '', 'Insert a YouTube video': '', - 'Insert current date': '', - 'Insert current time': '', - 'Print': '', 'Maximize': '', 'View source': '', 'Description (optional):': '', @@ -70,8 +64,10 @@ 'Insert a Quote': '', 'Invalid YouTube video': '', 'Drop files here': '', - 'Left-to-Right': '', - 'Right-to-Left': '', + 'User Albums': '', + 'User Attachments': '', + 'More BBCode': '', + 'Insert an embed media like a YouTube video, facebook post or twitter status.': '', // month format, replace - with the date format separator and order in the // order used diff --git a/languages/tr.js b/languages/tr.js index 325a2cc68..1b3f784ed 100644 --- a/languages/tr.js +++ b/languages/tr.js @@ -9,8 +9,6 @@ 'Italic': 'İtalik', 'Underline': 'Altı çizgili', 'Strikethrough': 'Üstü çizgili', - 'Subscript': 'Simge', - 'Superscript': 'Üstsimge', 'Align left': 'Sola yasla', 'Center': 'Ortala', 'Align right': 'Sağa yasla', @@ -36,8 +34,6 @@ 'Insert a table': 'Tablo ekle', 'Insert a horizontal rule': 'Yatay ayraç ekle', 'Code': 'Kod', - 'Width (optional):': 'Genişlik (opsiyonel):', - 'Height (optional):': 'Yükseklik (opsiyonel):', 'Insert an image': 'Resim ekle', 'E-mail:': 'E-posta:', 'Insert an email': 'E-posta ekle', @@ -51,7 +47,6 @@ 'Insert a YouTube video': 'YouTube videosu ekle', 'Insert current date': 'Şuanki tarihi ekle', 'Insert current time': 'Şuanki saati ekle', - 'Print': 'Yazdır', 'View source': 'Kaynağı görüntüle', 'Description (optional):': 'Açıklama (opsiyonel):', 'Enter the image URL:': 'Resim URL\'sini girin:', diff --git a/languages/tw.js b/languages/tw.js index 833691216..9804c5896 100644 --- a/languages/tw.js +++ b/languages/tw.js @@ -10,8 +10,6 @@ 'Italic': '斜體', 'Underline': '底線', 'Strikethrough': '删除線', - 'Subscript': '下標', - 'Superscript': '上標', 'Align left': '靠左對齊', 'Center': '置中', 'Align right': '靠右對齊', @@ -37,8 +35,6 @@ 'Insert a table': '插入表格', 'Insert a horizontal rule': '插入分隔線', 'Code': '原始碼', - 'Width (optional):': '寬度(選填)', - 'Height (optional):': '高度(選填)', 'Insert an image': '插入圖片', 'E-mail:': 'Email', 'Insert an email': '插入Email', @@ -50,9 +46,6 @@ 'Video URL:': '影片網址', 'Insert': '插入', 'Insert a YouTube video': '插入 YouTube 影片', - 'Insert current date': '插入目前日期', - 'Insert current time': '插入目前時間', - 'Print': '列印', 'View source': '查看原始碼', 'Description (optional):': '描述(選填)', 'Enter the image URL:': '輸入圖片網址', diff --git a/languages/uk.js b/languages/uk.js index 121f8c82e..e6c4e180b 100644 --- a/languages/uk.js +++ b/languages/uk.js @@ -6,8 +6,6 @@ 'Italic': 'Курсив', 'Underline': 'Підкреслений', 'Strikethrough': 'Закреслений', - 'Subscript': 'Нижній індекс', - 'Superscript': 'Верхній індекс', 'Align left': 'Вирівняти по лівому краю', 'Center': 'Вирівняти по центру', 'Align right': 'Вирівняти по правому краю', @@ -34,8 +32,6 @@ 'Insert a horizontal rule': 'Додати горизонтальну лінію', 'Code': 'Код', 'Insert a Quote': 'Додати цитату', - 'Width (optional):': 'Ширина (необов\'язково):', - 'Height (optional):': 'Висота (необов\'язково):', 'Insert an image': 'Додати зображення', 'E-mail:': 'E-mail:', 'Insert an email': 'Додати E-mail', @@ -47,9 +43,6 @@ 'Video URL:': 'URL відео:', 'Insert': 'Вставити', 'Insert a YouTube video': 'Додати відео з YouTube', - 'Insert current date': 'Додати дату', - 'Insert current time': 'Додати час', - 'Print': 'Надрукувати', 'View source': 'Показати код', 'Maximize': 'Розгорнути редактор', dateFormat: 'day.month.year' diff --git a/languages/vi.js b/languages/vi.js index 07d5bc8ed..e730fc1c1 100644 --- a/languages/vi.js +++ b/languages/vi.js @@ -10,8 +10,6 @@ 'Italic': 'Nghiêng', 'Underline': 'Gạch chân', 'Strikethrough': 'Gạch giữa', - 'Subscript': 'Hệ số', - 'Superscript': 'Mũ', 'Align left': 'Căn trái', 'Center': 'Căn giữa', 'Align right': 'Căn phải', @@ -37,8 +35,6 @@ 'Insert a table': 'Thêm bảng', 'Insert a horizontal rule': 'Thêm thước ngang', 'Code': 'Mã code', - 'Width (optional):': 'Dài (không bắt buộc)', - 'Height (optional):': 'Rộng (không bắt buộc)', 'Insert an image': 'Chèn hình ảnh', 'E-mail:': 'E-mail', 'Insert an email': 'Chèn email', @@ -50,9 +46,6 @@ 'Video URL:': 'Đường dẫn của Video', 'Insert': 'Thêm vào', 'Insert a YouTube video': 'Chèn Youtube', - 'Insert current date': 'Chèn ngày hiện tại', - 'Insert current time': 'Chèn thời gian hiện tại', - 'Print': 'In ấn', 'View source': 'Xem mã nguồn', 'Description (optional):': 'Mô tả (không bắt buộc)', 'Enter the image URL:': 'Nhập vào đường dẫn của hình ảnh', diff --git a/package-lock.json b/package-lock.json index 40542b197..99b0a958d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@lodder/grunt-postcss": "^3.1.1", - "@rollup/plugin-node-resolve": "^15.2.1", + "@rollup/plugin-node-resolve": "^15.2.3", "autoprefixer": "^10.4.15", "cssnano": "^6.0.1", "grunt": "~1.6.1", @@ -21,20 +21,20 @@ "grunt-contrib-compress": "^2.0.0", "grunt-contrib-concat": "~2.1.0", "grunt-contrib-copy": "^1.0.0", - "grunt-contrib-less": "^3.0.0", "grunt-contrib-qunit": "^7.0.1", "grunt-contrib-uglify": "^5.2.2", "grunt-eslint": "^24.3.0", "grunt-rollup": "^12.0.0", + "grunt-sass": "^3.1.0", "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.1.6", - "jquery": "^3.7.0", - "less": "^4.2.0", + "jquery": "^3.7.1", "loader-utils": "^3.2.1", "qunit": "^2.19.4", "rangy": "^1.3.1", + "sass": "^1.77.8", "sinon": "^15.2.0", "time-grunt": "^2.0.0", "webpack": "^5.88.2", @@ -796,10 +796,11 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", - "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", @@ -812,7 +813,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^2.78.0||^3.0.0" + "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -821,10 +822,11 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -834,7 +836,7 @@ "node": ">=14.0.0" }, "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { @@ -1025,7 +1027,8 @@ "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/retry": { "version": "0.12.1", @@ -1785,6 +1788,7 @@ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -1836,9 +1840,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001523", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz", - "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==", + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "dev": true, "funding": [ { @@ -1853,7 +1857,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", @@ -2142,15 +2147,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, - "node_modules/copy-anything": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz", - "integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==", - "dev": true, - "dependencies": { - "is-what": "^3.12.0" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2463,10 +2459,11 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2698,19 +2695,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2981,7 +2965,8 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", @@ -3897,21 +3882,6 @@ "node": ">=0.8.0" } }, - "node_modules/grunt-contrib-less": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-3.0.0.tgz", - "integrity": "sha512-fBB8MUDCo5EgT7WdOVQnZq4GF+XCeFdnkhaxI7uepp8P973sH1jdodjF87c6d9WSHKgArJAGP5JEtthhdKVovg==", - "dev": true, - "dependencies": { - "async": "^3.2.0", - "chalk": "^4.1.0", - "less": "^4.1.1", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/grunt-contrib-qunit": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-7.0.1.tgz", @@ -4026,6 +3996,7 @@ "resolved": "https://registry.npmjs.org/grunt-rollup/-/grunt-rollup-12.0.0.tgz", "integrity": "sha512-f2aYSxUiSf7cylK/WoOBx5DQmM+XTZzdO3xe3YHssaKwHQQLSMxGV0j/eIfrvjhRFWPBf+CCW18iSt/hapawpQ==", "dev": true, + "license": "MIT", "dependencies": { "rollup": "^2.71.1" }, @@ -4036,6 +4007,19 @@ "grunt": ">=0.4.0" } }, + "node_modules/grunt-sass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", + "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, "node_modules/grunt/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -4337,18 +4321,12 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", "dev": true, - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -4448,6 +4426,7 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, + "license": "MIT", "dependencies": { "builtin-modules": "^3.3.0" }, @@ -4530,8 +4509,9 @@ "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" }, "node_modules/is-number": { "version": "7.0.0", @@ -4611,12 +4591,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -4741,10 +4715,11 @@ } }, "node_modules/jquery": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", - "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", - "dev": true + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -4868,72 +4843,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "dev": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/less/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5326,47 +5235,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", - "dev": true, - "optional": true, - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -5805,15 +5673,6 @@ "node": ">=0.10.0" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -6469,13 +6328,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true, - "optional": true - }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -6785,10 +6637,11 @@ } }, "node_modules/rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -6834,12 +6687,23 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "node_modules/sass": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "dev": true, - "optional": true + "license": "MIT", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } }, "node_modules/schema-utils": { "version": "3.3.0", @@ -8837,9 +8701,9 @@ } }, "@rollup/plugin-node-resolve": { - "version": "15.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz", - "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, "requires": { "@rollup/pluginutils": "^5.0.1", @@ -8851,9 +8715,9 @@ } }, "@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, "requires": { "@types/estree": "^1.0.0", @@ -9688,9 +9552,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001523", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz", - "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==", + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "dev": true }, "chalk": { @@ -9913,15 +9777,6 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, - "copy-anything": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz", - "integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==", - "dev": true, - "requires": { - "is-what": "^3.12.0" - } - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -10151,9 +10006,9 @@ "dev": true }, "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true }, "default-gateway": { @@ -10328,16 +10183,6 @@ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "requires": { - "prr": "~1.0.1" - } - }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -11249,18 +11094,6 @@ } } }, - "grunt-contrib-less": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-less/-/grunt-contrib-less-3.0.0.tgz", - "integrity": "sha512-fBB8MUDCo5EgT7WdOVQnZq4GF+XCeFdnkhaxI7uepp8P973sH1jdodjF87c6d9WSHKgArJAGP5JEtthhdKVovg==", - "dev": true, - "requires": { - "async": "^3.2.0", - "chalk": "^4.1.0", - "less": "^4.1.1", - "lodash": "^4.17.21" - } - }, "grunt-contrib-qunit": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-7.0.1.tgz", @@ -11354,6 +11187,13 @@ "rollup": "^2.71.1" } }, + "grunt-sass": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", + "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", + "dev": true, + "requires": {} + }, "gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -11573,12 +11413,11 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true + "immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true }, "import-fresh": { "version": "3.3.0", @@ -11709,7 +11548,7 @@ "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true }, "is-number": { @@ -11763,12 +11602,6 @@ "unc-path-regex": "^0.1.2" } }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -11865,9 +11698,9 @@ } }, "jquery": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", - "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "dev": true }, "js-tokens": { @@ -11973,57 +11806,6 @@ } } }, - "less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "dev": true, - "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "parse-node-version": "^1.0.1", - "source-map": "~0.6.0", - "tslib": "^2.3.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - } - } - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -12334,40 +12116,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -12692,12 +12440,6 @@ "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", "dev": true }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -13126,13 +12868,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true, - "optional": true - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -13354,9 +13089,9 @@ } }, "rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -13383,12 +13118,16 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "sass": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "dev": true, - "optional": true + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } }, "schema-utils": { "version": "3.3.0", diff --git a/package.json b/package.json index 600230445..657aefd26 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ }, "devDependencies": { "@lodder/grunt-postcss": "^3.1.1", - "@rollup/plugin-node-resolve": "^15.2.1", + "@rollup/plugin-node-resolve": "^15.2.3", "autoprefixer": "^10.4.15", "cssnano": "^6.0.1", "grunt": "~1.6.1", @@ -58,20 +58,20 @@ "grunt-contrib-compress": "^2.0.0", "grunt-contrib-concat": "~2.1.0", "grunt-contrib-copy": "^1.0.0", - "grunt-contrib-less": "^3.0.0", "grunt-contrib-qunit": "^7.0.1", "grunt-contrib-uglify": "^5.2.2", "grunt-eslint": "^24.3.0", "grunt-rollup": "^12.0.0", + "grunt-sass": "^3.1.0", "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.1.6", - "jquery": "^3.7.0", - "less": "^4.2.0", + "jquery": "^3.7.1", "loader-utils": "^3.2.1", "qunit": "^2.19.4", "rangy": "^1.3.1", + "sass": "^1.77.8", "sinon": "^15.2.0", "time-grunt": "^2.0.0", "webpack": "^5.88.2", diff --git a/src/formats/bbcode.js b/src/formats/bbcode.js index 4a25c2f54..50b0bab7f 100644 --- a/src/formats/bbcode.js +++ b/src/formats/bbcode.js @@ -10,22 +10,22 @@ * @fileoverview SCEditor BBCode Format * @author Sam Clarke */ -(function (sceditor) { +(function(sceditor) { /*eslint max-depth: off*/ - 'use strict'; - var escapeEntities = sceditor.escapeEntities; + + var escapeEntities = sceditor.escapeEntities; var escapeUriScheme = sceditor.escapeUriScheme; - var dom = sceditor.dom; - var utils = sceditor.utils; + var dom = sceditor.dom; + var utils = sceditor.utils; - var css = dom.css; - var attr = dom.attr; - var is = dom.is; + var css = dom.css; + var attr = dom.attr; + var is = dom.is; var extend = utils.extend; - var each = utils.each; + var each = utils.each; - var EMOTICON_DATA_ATTR = 'data-sceditor-emoticon'; + var editorOptions; var getEditorCommand = sceditor.command.get; @@ -63,11 +63,8 @@ strike: { txtExec: ['[s]', '[/s]'] }, - subscript: { - txtExec: ['[sub]', '[/sub]'] - }, - superscript: { - txtExec: ['[sup]', '[/sup]'] + mark: { + txtExec: ['[h]', '[/h]'] }, left: { txtExec: ['[left]', '[/left]'] @@ -82,15 +79,15 @@ txtExec: ['[justify]', '[/justify]'] }, font: { - txtExec: function (caller) { + txtExec: function(caller) { var editor = this; getEditorCommand('font')._dropDown( editor, caller, - function (fontName) { + function(fontName) { editor.insertText( - '[font=' + fontName + ']', + `[font=${fontName}]`, '[/font]' ); } @@ -98,15 +95,15 @@ } }, size: { - txtExec: function (caller) { + txtExec: function(caller) { var editor = this; getEditorCommand('size')._dropDown( editor, caller, - function (fontSize) { + function(fontSize) { editor.insertText( - '[size=' + fontSize + ']', + `[size=${fontSize}]`, '[/size]' ); } @@ -114,15 +111,15 @@ } }, color: { - txtExec: function (caller) { + txtExec: function(caller) { var editor = this; getEditorCommand('color')._dropDown( editor, caller, - function (color) { + function(color) { editor.insertText( - '[color=' + color + ']', + `[color=${color}]`, '[/color]' ); } @@ -130,88 +127,104 @@ } }, bulletlist: { - txtExec: function (caller, selected) { + txtExec: function(caller, selected) { this.insertText( - '[ul]\n[li]' + - selected.split(/\r?\n/).join('[/li]\n[li]') + - '[/li]\n[/ul]' + `[list]\n[list]${selected.split(/\r?\n/).join('[/li]\n[li]')}[/li]\n[/ul]` ); } }, orderedlist: { - txtExec: function (caller, selected) { + txtExec: function(caller, selected) { this.insertText( - '[ol]\n[li]' + - selected.split(/\r?\n/).join('[/li]\n[li]') + - '[/li]\n[/ol]' + `[list=I]\n[li]${selected.split(/\r?\n/).join('[/li]\n[li]')}[/li]\n[/list]` ); } }, table: { txtExec: ['[table][tr][td]', '[/td][/tr][/table]'] }, - horizontalrule: { - txtExec: ['[hr]'] - }, code: { - txtExec: ['[code]', '[/code]'] + txtExec: function(caller) { + var editor = this; + + getEditorCommand('code')._dropDown( + editor, + caller, + function(language) { + editor.insertText( + `[code=${language}]`, + '[/code]' + ); + } + ); + } + }, + extensions: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('extensions')._dropDown( + editor, + caller, + function(extension) { + editor.insertText( + `[${extension}]`, + `[/${extension}]` + ); + } + ); + } }, image: { - txtExec: function (caller, selected) { - var editor = this; + txtExec: function(caller, selected) { + var editor = this; getEditorCommand('image')._dropDown( editor, caller, - selected, - function (url, width, height) { - var attrs = ''; - - if (width) { - attrs += ' width=' + width; - } - - if (height) { - attrs += ' height=' + height; + function(url, text) { + if (text || selected) { + editor.insertText( + `[img=${url}]${text || selected || url}[/img]` + ); + } else { + editor.insertText(`[img]${url}[/img]`); } - - editor.insertText( - '[img' + attrs + ']' + url + '[/img]' - ); } ); } }, email: { - txtExec: function (caller, selected) { - var editor = this; + txtExec: function(caller, selected) { + var editor = this; getEditorCommand('email')._dropDown( editor, caller, - function (url, text) { + function(url, text) { editor.insertText( - '[email=' + url + ']' + - (text || selected || url) + - '[/email]' + `[email=${url}]${text || selected || url}[/email]` ); } ); } }, link: { - txtExec: function (caller, selected) { - var editor = this; + txtExec: function(caller, selected) { + var editor = this; getEditorCommand('link')._dropDown( editor, caller, - function (url, text) { - editor.insertText( - '[url=' + url + ']' + - (text || selected || url) + - '[/url]' - ); + function(url, text) { + if (selected || text) { + editor.insertText( + `[url=${url}]${text || selected || url}[/url]` + ); + } else { + editor.insertText(`[url]${url}[/url]`); + } + } ); } @@ -219,24 +232,100 @@ quote: { txtExec: ['[quote]', '[/quote]'] }, - youtube: { - txtExec: function (caller) { + + userlink: { + txtExec: ['[userlink]', '[/userlink]'] + }, + albums: { + txtExec: function(caller) { var editor = this; - getEditorCommand('youtube')._dropDown( + getEditorCommand('albums')._dropDown( editor, caller, - function (id) { - editor.insertText('[youtube]' + id + '[/youtube]'); + function(url) { + editor.insertText(`[albumid]${url}[/albumid]`); } ); } }, - rtl: { - txtExec: ['[rtl]', '[/rtl]'] + attachments: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('attachments')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[attach]${url}[/attach]`); + } + ); + } }, - ltr: { - txtExec: ['[ltr]', '[/ltr]'] + media: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('media')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[media]${url}[/media]`); + } + ); + } + }, + vimeo: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('vimeo')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[vimeo]${url}[/vimeo]`); + } + ); + } + }, + instagram: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('instagram')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[instagram]${url}[/instagram]`); + } + ); + } + }, + facebook: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('facebook')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[facebook]${url}[/facebook]`); + } + ); + } + }, + youtube: { + txtExec: function(caller) { + var editor = this; + + getEditorCommand('youtube')._dropDown( + editor, + caller, + function(url) { + editor.insertText(`[youtube]${url}[/youtube]`); + } + ); + } } }; @@ -317,6 +406,18 @@ }, // END_COMMAND + // START_COMMAND: mark + h: { + tags: { + h: null, + mark: null + }, + format: '[h]{0}[/h]', + html: '{0}' + }, + // END_COMMAND + + // START_COMMAND: Font font: { tags: { @@ -328,15 +429,14 @@ 'font-family': null }, quoteType: QuoteType.never, - format: function (element, content) { + format: function(element, content) { var font; if (!is(element, 'font') || !(font = attr(element, 'face'))) { font = css(element, 'font-family'); } - return '[font=' + _stripQuotes(font) + ']' + - content + '[/font]'; + return `[font=${_stripQuotes(font)}]${content}[/font]`; }, html: '{0}' }, @@ -352,9 +452,9 @@ styles: { 'font-size': null }, - format: function (element, content) { - var fontSize = attr(element, 'size'), - size = 2; + format: function(element, content) { + var fontSize = attr(element, 'size'), + size = 2; if (!fontSize) { fontSize = css(element, 'fontSize'); @@ -387,7 +487,7 @@ size = fontSize; } - return '[size=' + size + ']' + content + '[/size]'; + return `[size=${size}]${content}[/size]`; }, html: '{!0}' }, @@ -404,20 +504,17 @@ color: null }, quoteType: QuoteType.never, - format: function (elm, content) { - var color; + format: function(elm, content) { + var color; if (!is(elm, 'font') || !(color = attr(elm, 'color'))) { color = elm.style.color || css(elm, 'color'); } - return '[color=' + _normaliseColour(color) + ']' + - content + '[/color]'; + return `[color=${_normaliseColour(color)}]${content}[/color]`; }, - html: function (token, attrs, content) { - return '' + content + ''; + html: function(token, attrs, content) { + return `${content}`; } }, // END_COMMAND @@ -430,13 +527,14 @@ breakStart: true, isInline: false, skipLastLineBreak: true, - format: '[ul]{0}[/ul]', + format: '[list]{0}[/list]', html: '
    {0}
' }, list: { breakStart: true, isInline: false, skipLastLineBreak: true, + format: '[list]{0}[/list]', html: '
    {0}
' }, ol: { @@ -446,7 +544,7 @@ breakStart: true, isInline: false, skipLastLineBreak: true, - format: '[ol]{0}[/ol]', + format: '[list=I]{0}[/list]', html: '
    {0}
' }, li: { @@ -474,7 +572,7 @@ isHtmlInline: true, skipLastLineBreak: true, format: '[table]{0}[/table]', - html: '{0}
' + html: '{0}
' }, tr: { tags: { @@ -501,23 +599,7 @@ allowsEmpty: true, isInline: false, format: '[td]{0}[/td]', - html: '{0}' - }, - // END_COMMAND - - // START_COMMAND: Emoticons - emoticon: { - allowsEmpty: true, - tags: { - img: { - src: null, - 'data-sceditor-emoticon': null - } - }, - format: function (element, content) { - return attr(element, EMOTICON_DATA_ATTR) + content; - }, - html: '{0}' + html: '{0}' }, // END_COMMAND @@ -539,62 +621,73 @@ allowsEmpty: true, tags: { img: { - src: null + src: null, + class: 'img-user-posted img-thumbnail' } }, allowedChildren: ['#'], quoteType: QuoteType.never, - format: function (element, content) { - var width, height, - attribs = '', - style = function (name) { - return element.style ? element.style[name] : null; - }; - - // check if this is an emoticon image - if (attr(element, EMOTICON_DATA_ATTR)) { - return content; - } + format: function(element) { + var desc; - width = attr(element, 'width') || style('width'); - height = attr(element, 'height') || style('height'); + desc = attr(element, 'alt'); - // only add width and height if one is specified - if ((element.complete && (width || height)) || - (width && height)) { - - attribs = '=' + dom.width(element) + 'x' + - dom.height(element); + if (desc) { + return `[img=${attr(element, 'src')}]${desc}[/img]`; } - return '[img' + attribs + ']' + attr(element, 'src') + '[/img]'; + return `[img]${attr(element, 'src')}[/img]`; }, - html: function (token, attrs, content) { - var undef, width, height, match, - attribs = ''; - - // handle [img width=340 height=240]url[/img] - width = attrs.width; - height = attrs.height; + html: function(token, attrs, content) { + attrs.defaultattr = + escapeEntities(attrs.defaultattr, true) || content; - // handle [img=340x240]url[/img] - if (attrs.defaultattr) { - match = attrs.defaultattr.split(/x/i); + return `${content
+				}`; + } + }, + // END_COMMAND - width = match[0]; - height = (match.length === 2 ? match[1] : match[0]); + // START_COMMAND: userlink + userlink: { + allowsEmpty: true, + tags: { + span: { + class: 'badge rounded-pill text-bg-secondary fs-6' } + }, + format: function(element) { + return `[userlink]${attr(element, 'data-user')}[/userlink]`; + }, + html: function(token, attrs, content) { - if (width !== undef) { - attribs += ' width="' + escapeEntities(width, true) + '"'; - } + return `${escapeEntities(content)}`; + } + }, + // END_COMMAND - if (height !== undef) { - attribs += ' height="' + escapeEntities(height, true) + '"'; + // START_COMMAND: albumimg + albumimg: { + allowsEmpty: true, + tags: { + div: { + src: null, + class: 'card text-bg-dark' } + }, + allowedChildren: ['#'], + quoteType: QuoteType.never, + format: function(element) { + return `[albumimg]${attr(element, 'alt')}[/albumimg]`; + }, + html: function(token, attrs, content) { + attrs.defaultattr = + escapeEntities(attrs.defaultattr, true) || content; - return ''; + return `
`; } }, // END_COMMAND @@ -608,24 +701,22 @@ } }, quoteType: QuoteType.never, - format: function (element, content) { - var url = attr(element, 'href'); + format: function(element, content) { + const url = attr(element, 'href'); // make sure this link is not an e-mail, // if it is return e-mail BBCode if (url.substr(0, 7) === 'mailto:') { - return '[email="' + url.substr(7) + '"]' + - content + '[/email]'; + return `[email="${url.substr(7)}"]${content}[/email]`; } - return '[url=' + url + ']' + content + '[/url]'; + return `[url=${url}]${content}[/url]`; }, - html: function (token, attrs, content) { + html: function(token, attrs, content) { attrs.defaultattr = escapeEntities(attrs.defaultattr, true) || content; - return '' + - content + ''; + return `${content}`; } }, // END_COMMAND @@ -633,10 +724,8 @@ // START_COMMAND: E-mail email: { quoteType: QuoteType.never, - html: function (token, attrs, content) { - return '' + content + ''; + html: function(token, attrs, content) { + return `${content}`; } }, // END_COMMAND @@ -644,49 +733,51 @@ // START_COMMAND: Quote quote: { tags: { - blockquote: null + div: { + class: 'border rounded mx-3 mb-3 p-3 border-secondary shadow-sm' + } }, isInline: false, quoteType: QuoteType.never, - format: function (element, content) { - var authorAttr = 'data-author'; - var author = ''; + format: function(element, content) { + var author = ''; var cite; - var children = element.children; + const children = element.children; - for (var i = 0; !cite && i < children.length; i++) { + for (let i = 0; !cite && i < children.length; i++) { if (is(children[i], 'cite')) { cite = children[i]; } } - if (cite || attr(element, authorAttr)) { - author = cite && cite.textContent || - attr(element, authorAttr); - - attr(element, authorAttr, author); + if (cite) { + author = cite && cite.textContent; if (cite) { element.removeChild(cite); } - content = this.elementToBbcode(element); - author = '=' + author.replace(/(^\s+|\s+$)/g, ''); + content = this.elementToBbcode(element); + + author = `=${author.replace(/(^\s+|\s+$)/g, '')}`; if (cite) { element.insertBefore(cite, element.firstChild); } } - return '[quote' + author + ']' + content + '[/quote]'; + return `[quote${author}]${content}[/quote]`; }, - html: function (token, attrs, content) { + html: function(token, attrs, content) { if (attrs.defaultattr) { - content = '' + escapeEntities(attrs.defaultattr) + - '' + content; + content = content + + '' + + escapeEntities(attrs.defaultattr) + + ''; } - return '
' + content + '
'; + return `
${ + content}
`; } }, // END_COMMAND @@ -694,13 +785,25 @@ // START_COMMAND: Code code: { tags: { - code: null + code: { + class: null + } }, isInline: false, allowedChildren: ['#', '#newline'], - format: '[code]{0}[/code]', - html: '{0}' + format: function(element, content) { + var codeLanguage; + + if (!is(element, 'code') || !(codeLanguage = attr(element, 'class'))) { + codeLanguage = element.className.replace('language-', ''); + } + + return `[code=${codeLanguage.replace('language-', '')}]${content}[/code]`; + }, + html: + '
{0}
' }, + // END_COMMAND @@ -772,22 +875,103 @@ }, // END_COMMAND + // START_COMMAND: Facebook + facebook: { + allowsEmpty: true, + tags: { + div: { + 'data-facebook-url': null + } + }, + format: function(element, content) { + element = attr(element, 'data-facebook-url'); + + return element ? `[facebook]${element}[/facebook]` : content; + }, + html: function(token, attrs, content) { + const url = content; + + return `
`; + } + }, + // END_COMMAND + + // START_COMMAND: Instagram + instagram: { + allowsEmpty: true, + tags: { + div: { + 'data-instagram-url': null + } + }, + format: function(element, content) { + element = attr(element, 'data-instagram-url'); + + return element ? `[instagram]${element}[/instagram]` : content; + }, + html: function(token, attrs, content) { + var id = content; + + const url = content; + + var id = url.match(/\/(p|tv|reel)\/(.*?)\//)[2]; + + return `
`; + } + }, + // END_COMMAND + + // START_COMMAND: Vimeo + vimeo: { + allowsEmpty: true, + tags: { + div: { + 'data-vimeo-url': null + } + }, + format: function(element, content) { + element = attr(element, 'data-vimeo-url'); + + return element ? `[vimeo]${element}[/vimeo]` : content; + }, + html: function(token, attrs, content) { + const url = content; + + const id = url.match(/vimeo\..*\/(\d+)(?:$|\/)/)[1]; + + return `
`; + } + }, + // END_COMMAND + + // START_COMMAND: YouTube youtube: { allowsEmpty: true, tags: { - iframe: { - 'data-youtube-id': null + div: { + 'data-youtube-url': null } }, - format: function (element, content) { - element = attr(element, 'data-youtube-id'); + format: function(element, content) { + element = attr(element, 'data-youtube-url'); - return element ? '[youtube]' + element + '[/youtube]' : content; + return element ? `[youtube]${element}[/youtube]` : content; }, - html: '' + html: function(token, attrs, content) { + const url = content; + + const id = content.match(/(?:v=|v\/|embed\/|youtu.be\/)?([a-zA-Z0-9_-]{11})/)[1]; + + return `
`; + } }, // END_COMMAND @@ -833,25 +1017,26 @@ * @since 2.0.0 */ function formatBBCodeString(str, obj) { - return str.replace(/\{([^}]+)\}/g, function (match, group) { - var undef, - escape = true; - - if (group.charAt(0) === '!') { - escape = false; - group = group.substring(1); - } + return str.replace(/\{([^}]+)\}/g, + function(match, group) { + var undef, + escape = true; + + if (group.charAt(0) === '!') { + escape = false; + group = group.substring(1); + } - if (group === '0') { - escape = false; - } + if (group === '0') { + escape = false; + } - if (obj[group] === undef) { - return match; - } + if (obj[group] === undef) { + return match; + } - return escape ? escapeEntities(obj[group], true) : obj[group]; - }); + return escape ? escapeEntities(obj[group], true) : obj[group]; + }); } function isFunction(fn) { @@ -865,8 +1050,7 @@ * @since v1.4.0 */ function _stripQuotes(str) { - return str ? - str.replace(/\\(.)/g, '$1').replace(/^(["'])(.*?)\1$/, '$2') : str; + return str ? str.replace(/\\(.)/g, '$1').replace(/^(["'])(.*?)\1$/, '$2') : str; } /** @@ -879,14 +1063,13 @@ * @since v1.4.0 */ function _formatString(str) { - var undef; + var undef; var args = arguments; - return str.replace(/\{(\d+)\}/g, function (_, matchNum) { - return args[matchNum - 0 + 1] !== undef ? - args[matchNum - 0 + 1] : - '{' + matchNum + '}'; - }); + return str.replace(/\{(\d+)\}/g, + function(_, matchNum) { + return args[matchNum - 0 + 1] !== undef ? args[matchNum - 0 + 1] : `{${matchNum}}`; + }); } var TOKEN_OPEN = 'open'; @@ -923,14 +1106,14 @@ */ // eslint-disable-next-line max-params function TokenizeToken(type, name, val, attrs, children, closing) { - var base = this; + const base = this; - base.type = type; - base.name = name; - base.val = val; - base.attrs = attrs || {}; + base.type = type; + base.name = name; + base.val = val; + base.attrs = attrs || {}; base.children = children || []; - base.closing = closing || null; + base.closing = closing || null; }; TokenizeToken.prototype = { @@ -940,8 +1123,8 @@ * * @return {TokenizeToken} */ - clone: function () { - var base = this; + clone: function() { + const base = this; return new TokenizeToken( base.type, @@ -959,16 +1142,16 @@ * @return {TokenizeToken} The right half of the split token or * empty clone if invalid splitAt lcoation */ - splitAt: function (splitAt) { + splitAt: function(splitAt) { var offsetLength; - var base = this; - var clone = base.clone(); - var offset = base.children.indexOf(splitAt); + const base = this; + const clone = base.clone(); + const offset = base.children.indexOf(splitAt); if (offset > -1) { // Work out how many items are on the right side of the split // to pass to splice() - offsetLength = base.children.length - offset; + offsetLength = base.children.length - offset; clone.children = base.children.splice(offset, offsetLength); } @@ -1003,12 +1186,12 @@ * @return {array} * @memberOf BBCodeParser.prototype */ - base.tokenize = function (str) { - var matches, type, i; - var tokens = []; + base.tokenize = function(str) { + var matches, type, i; + const tokens = []; // The token types in reverse order of precedence // (they're looped in reverse) - var tokenTypes = [ + const tokenTypes = [ { type: TOKEN_CONTENT, regex: /^([^\[\r\n]+|\[)/ @@ -1037,7 +1220,7 @@ // Check if the string matches any of the tokens if (!(matches = str.match(tokenTypes[i].regex)) || - !matches[0]) { + !matches[0]) { continue; } @@ -1072,9 +1255,9 @@ * @private */ function tokenizeTag(type, val) { - var matches, attrs, name, - openRegex = /\[([^\]\s=]+)(?:([^\]]+))?\]/, - closeRegex = /\[\/([^\[\]]+)\]/; + var matches, attrs, name; + const openRegex = /\[([^\]\s=]+)(?:([^\]]+))?\]/; + const closeRegex = /\[\/([^\[\]]+)\]/; // Extract the name and attributes from opening tags and // just the name from closing tags. @@ -1097,7 +1280,8 @@ // Treat all tokens without a name and // all unknown BBCodes as content - if (!name || ((type === TOKEN_OPEN || type === TOKEN_CLOSE) && + if (!name || + ((type === TOKEN_OPEN || type === TOKEN_CLOSE) && !bbcodeHandlers[name])) { type = TOKEN_CONTENT; @@ -1116,7 +1300,7 @@ * @private */ function tokenizeAttrs(attrs) { - var matches, + var matches /* ([^\s=]+) Anything that's not a space or equals = Equals sign = @@ -1137,9 +1321,9 @@ would be a new attribute ) ) - */ - attrRegex = /([^\s=]+)=(?:(?:(["'])((?:\\\2|[^\2])*?)\2)|((?:.(?!\s\S+=))*.))/g, - ret = {}; + */; + const attrRegex = /([^\s=]+)=(?:(?:(["'])((?:\\\2|[^\2])*?)\2)|((?:.(?!\s\S+=))*.))/g; + const ret = {}; // if only one attribute then remove the = from the start and // strip any quotes @@ -1147,7 +1331,7 @@ ret.defaultattr = _stripQuotes(attrs.substr(1)); } else { if (attrs.charAt(0) === '=') { - attrs = 'defaultattr' + attrs; + attrs = `defaultattr${attrs}`; } // No need to strip quotes here, the regex will do that. @@ -1170,9 +1354,9 @@ * @return {array} Array of BBCode objects * @memberOf BBCodeParser.prototype */ - base.parse = function (str, preserveNewLines) { - var ret = parseTokens(base.tokenize(str)); - var opts = base.opts; + base.parse = function(str, preserveNewLines) { + const ret = parseTokens(base.tokenize(str)); + const opts = base.opts; if (opts.fixInvalidNesting) { fixNesting(ret); @@ -1222,8 +1406,8 @@ * @private */ function isChildAllowed(parent, child) { - var parentBBCode = parent ? bbcodeHandlers[parent.name] : {}, - allowedChildren = parentBBCode.allowedChildren; + const parentBBCode = parent ? bbcodeHandlers[parent.name] : {}; + const allowedChildren = parentBBCode.allowedChildren; if (base.opts.fixInvalidChildren && allowedChildren) { return allowedChildren.indexOf(child.name || '#') > -1; @@ -1242,15 +1426,20 @@ * @private */ function parseTokens(toks) { - var token, bbcode, curTok, clone, i, next, - cloned = [], - output = [], - openTags = [], + var token, + bbcode, + curTok, + clone, + i, + next, + cloned = [], + output = [], + openTags = [], /** * Returns the currently open tag or undefined * @return {TokenizeToken} */ - currentTag = function () { + currentTag = function() { return last(openTags); }, /** @@ -1259,7 +1448,7 @@ * @param {TokenizeToken} token * @private */ - addTag = function (token) { + addTag = function(token) { if (currentTag()) { currentTag().children.push(token); } else { @@ -1271,7 +1460,7 @@ * @param {string} name * @return {Void} */ - closesCurrentTag = function (name) { + closesCurrentTag = function(name) { return currentTag() && (bbcode = bbcodeHandlers[currentTag().name]) && bbcode.closedBy && @@ -1297,8 +1486,9 @@ if (!isChildAllowed(currentTag(), token)) { // exclude closing tags of current tag - if (token.type !== TOKEN_CLOSE || !currentTag() || - token.name !== currentTag().name) { + if (token.type !== TOKEN_CLOSE || + !currentTag() || + token.name !== currentTag().name) { token.name = '#'; token.type = TOKEN_CONTENT; } @@ -1306,8 +1496,8 @@ switch (token.type) { case TOKEN_OPEN: - // Check it this closes a parent, - // e.g. for lists [*]one [*]two + // Check it this closes a parent, + // e.g. for lists [*]one [*]two if (closesCurrentTag(token.name)) { openTags.pop(); } @@ -1320,9 +1510,10 @@ // list of open tags. If has the closedBy property then // it is closed by other tags so include everything as // it's children until one of those tags is reached. - if (bbcode && !bbcode.isSelfClosing && - (bbcode.closedBy || - hasTag(token.name, TOKEN_CLOSE, toks))) { + if (bbcode && + !bbcode.isSelfClosing && + (bbcode.closedBy || + hasTag(token.name, TOKEN_CLOSE, toks))) { openTags.push(token); } else if (!bbcode || !bbcode.isSelfClosing) { token.type = TOKEN_CONTENT; @@ -1330,10 +1521,11 @@ break; case TOKEN_CLOSE: - // check if this closes the current tag, - // e.g. [/list] would close an open [*] - if (currentTag() && token.name !== currentTag().name && - closesCurrentTag('/' + token.name)) { + // check if this closes the current tag, + // e.g. [/list] would close an open [*] + if (currentTag() && + token.name !== currentTag().name && + closesCurrentTag(`/${token.name}`)) { openTags.pop(); } @@ -1401,28 +1593,30 @@ break; case TOKEN_NEWLINE: - // handle things like - // [*]list\nitem\n[*]list1 - // where it should come out as - // [*]list\nitem[/*]\n[*]list1[/*] - // instead of - // [*]list\nitem\n[/*][*]list1[/*] - if (currentTag() && next && closesCurrentTag( + // handle things like + // [*]list\nitem\n[*]list1 + // where it should come out as + // [*]list\nitem[/*]\n[*]list1[/*] + // instead of + // [*]list\nitem\n[/*][*]list1[/*] + if (currentTag() && + next && + closesCurrentTag( (next.type === TOKEN_CLOSE ? '/' : '') + next.name )) { - // skip if the next tag is the closing tag for - // the option tag, i.e. [/*] + // skip if the next tag is the closing tag for + // the option tag, i.e. [/*] if (!(next.type === TOKEN_CLOSE && - next.name === currentTag().name)) { + next.name === currentTag().name)) { bbcode = bbcodeHandlers[currentTag().name]; if (bbcode && bbcode.breakAfter) { openTags.pop(); } else if (bbcode && - bbcode.isInline === false && - base.opts.breakAfterBlock && - bbcode.breakAfter !== false) { + bbcode.isInline === false && + base.opts.breakAfterBlock && + bbcode.breakAfter !== false) { openTags.pop(); } } @@ -1467,8 +1661,14 @@ * @return {void} */ function normaliseNewLines(children, parent, onlyRemoveBreakAfter) { - var token, left, right, parentBBCode, bbcode, - removedBreakEnd, removedBreakBefore, remove; + var token, + left, + right, + parentBBCode, + bbcode, + removedBreakEnd, + removedBreakBefore, + remove; var childrenLength = children.length; // TODO: this function really needs tidying up if (parent) { @@ -1482,13 +1682,14 @@ } if (token.type === TOKEN_NEWLINE) { - left = i > 0 ? children[i - 1] : null; - right = i < childrenLength - 1 ? children[i + 1] : null; + left = i > 0 ? children[i - 1] : null; + right = i < childrenLength - 1 ? children[i + 1] : null; remove = false; // Handle the start and end new lines // e.g. [tag]\n and \n[/tag] - if (!onlyRemoveBreakAfter && parentBBCode && + if (!onlyRemoveBreakAfter && + parentBBCode && parentBBCode.isSelfClosing !== true) { // First child of parent so must be opening line break // (breakStartBlock, breakStart) e.g. [tag]\n @@ -1502,10 +1703,10 @@ if (parentBBCode.breakStart) { remove = true; } - // Last child of parent so must be end line break - // (breakEndBlock, breakEnd) - // e.g. \n[/tag] - // remove last line break (breakEndBlock, breakEnd) + // Last child of parent so must be end line break + // (breakEndBlock, breakEnd) + // e.g. \n[/tag] + // remove last line break (breakEndBlock, breakEnd) } else if (!removedBreakEnd && !right) { if (parentBBCode.isInline === false && base.opts.breakEndBlock && @@ -1539,8 +1740,10 @@ } } - if (!onlyRemoveBreakAfter && !removedBreakBefore && - right && right.type === TOKEN_OPEN) { + if (!onlyRemoveBreakAfter && + !removedBreakBefore && + right && + right.type === TOKEN_OPEN) { if ((bbcode = bbcodeHandlers[right.name])) { if (bbcode.isInline === false && @@ -1572,7 +1775,8 @@ // would be. removedBreakBefore = false; } else if (token.type === TOKEN_OPEN) { - normaliseNewLines(token.children, token, + normaliseNewLines(token.children, + token, onlyRemoveBreakAfter); } } @@ -1597,10 +1801,10 @@ * @private */ function fixNesting(children, parents, insideInline, rootArr) { - var token, i, parent, parentIndex, parentParentChildren, right; + var token, i, parent, parentIndex, parentParentChildren, right; - var isInline = function (token) { - var bbcode = bbcodeHandlers[token.name]; + const isInline = function(token) { + const bbcode = bbcodeHandlers[token.name]; return !bbcode || bbcode.isInline !== false; }; @@ -1619,15 +1823,14 @@ // if this is a blocklevel element inside an inline one then // split the parent at the block level element parent = last(parents); - right = parent.splitAt(token); + right = parent.splitAt(token); - parentParentChildren = parents.length > 1 ? - parents[parents.length - 2].children : rootArr; + parentParentChildren = parents.length > 1 ? parents[parents.length - 2].children : rootArr; // If parent inline is allowed inside this tag, clone it and // wrap this tags children in it. if (isChildAllowed(token, parent)) { - var clone = parent.clone(); + const clone = parent.clone(); clone.children = token.children; token.children = [clone]; } @@ -1641,17 +1844,22 @@ // insert the block level token and the right side after // the left side of the inline token parentParentChildren.splice( - parentIndex + 1, 0, token, right + parentIndex + 1, + 0, + token, + right ); // If token is a block and is followed by a newline, // then move the newline along with it to the new parent - var next = right.children[0]; + const next = right.children[0]; if (next && next.type === TOKEN_NEWLINE) { if (!isInline(token)) { right.children.splice(0, 1); parentParentChildren.splice( - parentIndex + 2, 0, next + parentIndex + 2, + 0, + next ); } } @@ -1683,17 +1891,17 @@ * @private */ function removeEmpty(tokens) { - var token, bbcode; + var token, bbcode; /** * Checks if all children are whitespace or not * @private */ - var isTokenWhiteSpace = function (children) { + const isTokenWhiteSpace = function(children) { var j = children.length; while (j--) { - var type = children[j].type; + const type = children[j].type; if (type === TOKEN_OPEN || type === TOKEN_CLOSE) { return false; @@ -1722,8 +1930,10 @@ // are all removed this one doesn't think it's not empty. removeEmpty(token.children); - if (isTokenWhiteSpace(token.children) && bbcode && - !bbcode.isSelfClosing && !bbcode.allowsEmpty) { + if (isTokenWhiteSpace(token.children) && + bbcode && + !bbcode.isSelfClosing && + !bbcode.allowsEmpty) { tokens.splice.apply(tokens, [i, 1].concat(token.children)); } } @@ -1739,11 +1949,11 @@ * @return {string} * @memberOf BBCodeParser.prototype */ - base.toHTML = function (str, preserveNewLines) { + base.toHTML = function(str, preserveNewLines) { return convertToHTML(base.parse(str, preserveNewLines), true); }; - base.toHTMLFragment = function (str, preserveNewLines) { + base.toHTMLFragment = function(str, preserveNewLines) { return convertToHTML(base.parse(str, preserveNewLines), false); }; @@ -1751,13 +1961,19 @@ * @private */ function convertToHTML(tokens, isRoot) { - var undef, token, bbcode, content, html, needsBlockWrap, - blockWrapOpen, isInline, lastChild, + var undef, + token, + bbcode, + content, + html, + needsBlockWrap, + blockWrapOpen, + isInline, + lastChild, ret = ''; - isInline = function (bbcode) { - return (!bbcode || (bbcode.isHtmlInline !== undef ? - bbcode.isHtmlInline : bbcode.isInline)) !== false; + isInline = function(bbcode) { + return (!bbcode || (bbcode.isHtmlInline !== undef ? bbcode.isHtmlInline : bbcode.isInline)) !== false; }; while (tokens.length > 0) { @@ -1780,7 +1996,7 @@ !bbcode.skipLastLineBreak) { // Add placeholder br to end of block level // elements - content += '
'; + //content += '
'; } if (!isFunction(bbcode.html)) { @@ -1798,7 +2014,8 @@ ); } } else { - html = token.val + content + + html = token.val + + content + (token.closing ? token.closing.val : ''); } } else if (token.type === TOKEN_NEWLINE) { @@ -1825,10 +2042,10 @@ ret += '\n'; blockWrapOpen = false; continue; - // content + // content } else { needsBlockWrap = isRoot; - html = escapeEntities(token.val, true); + html = escapeEntities(token.val, true); } if (needsBlockWrap && !blockWrapOpen) { @@ -1862,7 +2079,7 @@ * @return {string} * @memberOf BBCodeParser.prototype */ - base.toBBCode = function (str, preserveNewLines) { + base.toBBCode = function(str, preserveNewLines) { return convertToBBCode(base.parse(str, preserveNewLines)); }; @@ -1876,8 +2093,16 @@ * @private */ function convertToBBCode(toks) { - var token, attr, bbcode, isBlock, isSelfClosing, quoteType, - breakBefore, breakStart, breakEnd, breakAfter, + var token, + attr, + bbcode, + isBlock, + isSelfClosing, + quoteType, + breakBefore, + breakStart, + breakEnd, + breakAfter, ret = ''; while (toks.length > 0) { @@ -1885,29 +2110,34 @@ continue; } // TODO: tidy this - bbcode = bbcodeHandlers[token.name]; - isBlock = !(!bbcode || bbcode.isInline !== false); + bbcode = bbcodeHandlers[token.name]; + isBlock = !(!bbcode || bbcode.isInline !== false); isSelfClosing = bbcode && bbcode.isSelfClosing; - breakBefore = (isBlock && base.opts.breakBeforeBlock && + breakBefore = (isBlock && + base.opts.breakBeforeBlock && bbcode.breakBefore !== false) || (bbcode && bbcode.breakBefore); - breakStart = (isBlock && !isSelfClosing && + breakStart = (isBlock && + !isSelfClosing && base.opts.breakStartBlock && bbcode.breakStart !== false) || (bbcode && bbcode.breakStart); - breakEnd = (isBlock && base.opts.breakEndBlock && + breakEnd = (isBlock && + base.opts.breakEndBlock && bbcode.breakEnd !== false) || (bbcode && bbcode.breakEnd); - breakAfter = (isBlock && base.opts.breakAfterBlock && + breakAfter = (isBlock && + base.opts.breakAfterBlock && bbcode.breakAfter !== false) || (bbcode && bbcode.breakAfter); quoteType = (bbcode ? bbcode.quoteType : null) || - base.opts.quoteType || QuoteType.auto; + base.opts.quoteType || + QuoteType.auto; if (!bbcode && token.type === TOKEN_OPEN) { ret += token.val; @@ -1925,22 +2155,21 @@ } // Convert the tag and it's attributes to BBCode - ret += '[' + token.name; + ret += `[${token.name}`; if (token.attrs) { if (token.attrs.defaultattr) { - ret += '=' + quote( + ret += `=${quote( token.attrs.defaultattr, quoteType, 'defaultattr' - ); + )}`; delete token.attrs.defaultattr; } for (attr in token.attrs) { if (token.attrs.hasOwnProperty(attr)) { - ret += ' ' + attr + '=' + - quote(token.attrs[attr], quoteType, attr); + ret += ` ${attr}=${quote(token.attrs[attr], quoteType, attr)}`; } } } @@ -1961,7 +2190,7 @@ ret += '\n'; } - ret += '[/' + token.name + ']'; + ret += `[/${token.name}]`; } if (breakAfter) { @@ -1991,7 +2220,7 @@ * @private */ function quote(str, quoteType, name) { - var needsQuotes = /\s|=/.test(str); + const needsQuotes = /\s|=/.test(str); if (isFunction(quoteType)) { return quoteType(str, name); @@ -2002,7 +2231,7 @@ return str; } - return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'; + return `"${str.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`; } /** @@ -2139,7 +2368,7 @@ number = Math.max(0, Math.min(number, 255)).toString(16); - return number.length < 2 ? '0' + number : number; + return number.length < 2 ? `0${number}` : number; } /** @@ -2166,9 +2395,12 @@ // expand shorthand if ((match = colorStr.match(/#([0-9a-f])([0-9a-f])([0-9a-f])\s*?$/i))) { return '#' + - match[1] + match[1] + - match[2] + match[2] + - match[3] + match[3]; + match[1] + + match[1] + + match[2] + + match[2] + + match[3] + + match[3]; } return colorStr; @@ -2209,35 +2441,37 @@ * @private */ function buildBbcodeCache() { - each(bbcodeHandlers, function (bbcode, handler) { - var - isBlock = handler.isInline === false, - tags = bbcodeHandlers[bbcode].tags, - styles = bbcodeHandlers[bbcode].styles; - - if (styles) { - tagsToBBCodes['*'] = tagsToBBCodes['*'] || {}; - tagsToBBCodes['*'][isBlock] = - tagsToBBCodes['*'][isBlock] || {}; - tagsToBBCodes['*'][isBlock][bbcode] = [ - ['style', Object.entries(styles)] - ]; - } + each(bbcodeHandlers, + function(bbcode, handler) { + var + isBlock = handler.isInline === false; + const tags = bbcodeHandlers[bbcode].tags; + const styles = bbcodeHandlers[bbcode].styles; + + if (styles) { + tagsToBBCodes['*'] = tagsToBBCodes['*'] || {}; + tagsToBBCodes['*'][isBlock] = + tagsToBBCodes['*'][isBlock] || {}; + tagsToBBCodes['*'][isBlock][bbcode] = [ + ['style', Object.entries(styles)] + ]; + } - if (tags) { - each(tags, function (tag, values) { - if (values && values.style) { - values.style = Object.entries(values.style); - } + if (tags) { + each(tags, + function(tag, values) { + if (values && values.style) { + values.style = Object.entries(values.style); + } - tagsToBBCodes[tag] = tagsToBBCodes[tag] || {}; - tagsToBBCodes[tag][isBlock] = - tagsToBBCodes[tag][isBlock] || {}; - tagsToBBCodes[tag][isBlock][bbcode] = - values && Object.entries(values); - }); - } - }); + tagsToBBCodes[tag] = tagsToBBCodes[tag] || {}; + tagsToBBCodes[tag][isBlock] = + tagsToBBCodes[tag][isBlock] || {}; + tagsToBBCodes[tag][isBlock][bbcode] = + values && Object.entries(values); + }); + } + }); }; /** @@ -2249,19 +2483,21 @@ * @private */ function handleBlockNewlines(element, content) { - var tag = element.nodeName.toLowerCase(); - var isInline = dom.isInline; + const tag = element.nodeName.toLowerCase(); + const isInline = dom.isInline; if (!isInline(element, true) || tag === 'br') { - var isLastBlockChild, parent, parentLastChild, - previousSibling = element.previousSibling; + let isLastBlockChild; + let parent; + let parentLastChild; + let previousSibling = element.previousSibling; // Skips selection makers and ignored elements // Skip empty inline elements while (previousSibling && - previousSibling.nodeType === 1 && - !is(previousSibling, 'br') && - isInline(previousSibling, true) && - !previousSibling.firstChild) { + previousSibling.nodeType === 1 && + !is(previousSibling, 'br') && + isInline(previousSibling, true) && + !previousSibling.firstChild) { previousSibling = previousSibling.previousSibling; } @@ -2269,7 +2505,7 @@ // child of a block then it shouldn't cause a line break //
do { - parent = element.parentNode; + parent = element.parentNode; parentLastChild = parent && parent.lastChild; isLastBlockChild = parentLastChild === element; @@ -2288,10 +2524,11 @@ // // The second opening opening tag should cause a // line break because the previous sibing is inline. - if (tag !== 'br' && previousSibling && + if (tag !== 'br' && + previousSibling && !is(previousSibling, 'br') && isInline(previousSibling, true)) { - content = '\n' + content; + content = `\n${content}`; } } @@ -2310,10 +2547,10 @@ */ function handleTags(element, content, blockLevel) { function isStyleMatch(style) { - var property = style[0]; - var values = style[1]; - var val = dom.getStyle(element, property); - var parent = element.parentNode; + const property = style[0]; + const values = style[1]; + const val = dom.getStyle(element, property); + const parent = element.parentNode; // if the parent has the same style use that instead of this one // so you don't end up with [i]parent[i]child[/i][/i] @@ -2325,9 +2562,9 @@ } function createAttributeMatch(isStrict) { - return function (attribute) { - var name = attribute[0]; - var value = attribute[1]; + return function(attribute) { + const name = attribute[0]; + const value = attribute[1]; // code tags should skip most styles if (name === 'style' && element.nodeName === 'CODE') { @@ -2337,7 +2574,7 @@ if (name === 'style' && value) { return value[isStrict ? 'every' : 'some'](isStyleMatch); } else { - var val = attr(element, name); + const val = attr(element, name); return val && (!value || value.includes(val)); } @@ -2350,29 +2587,31 @@ } // loop all bbcodes for this tag - each(tagsToBBCodes[tag][blockLevel], function (bbcode, attrs) { - var fn, format, - isStrict = bbcodeHandlers[bbcode].strictMatch; - - if (typeof isStrict === 'undefined') { - isStrict = base.opts.strictMatch; - } + each(tagsToBBCodes[tag][blockLevel], + function(bbcode, attrs) { + var fn, + format, + isStrict = bbcodeHandlers[bbcode].strictMatch; + + if (typeof isStrict === 'undefined') { + isStrict = base.opts.strictMatch; + } - // Skip if the element doesn't have the attribute or the - // attribute doesn't match one of the required values - fn = isStrict ? 'every' : 'some'; - if (attrs && !attrs[fn](createAttributeMatch(isStrict))) { - return; - } + // Skip if the element doesn't have the attribute or the + // attribute doesn't match one of the required values + fn = isStrict ? 'every' : 'some'; + if (attrs && !attrs[fn](createAttributeMatch(isStrict))) { + return; + } - format = bbcodeHandlers[bbcode].format; - if (isFunction(format)) { - content = format.call(base, element, content); - } else { - content = _formatString(format, content); - } - return false; - }); + format = bbcodeHandlers[bbcode].format; + if (isFunction(format)) { + content = format.call(base, element, content); + } else { + content = _formatString(format, content); + } + return false; + }); } handleTag('*'); @@ -2391,74 +2630,71 @@ * @memberOf SCEditor.plugins.bbcode.prototype */ function elementToBbcode(element, hasCodeParent) { - var toBBCode = function (node, hasCodeParent, vChildren) { + var toBBCode = function(node, hasCodeParent, vChildren) { var ret = ''; - dom.traverse(node, function (node) { - var content = '', - nodeType = node.nodeType, - tag = node.nodeName.toLowerCase(), - isCodeTag = tag === 'code', - isEmoticon = tag === 'img' && - !!attr(node, EMOTICON_DATA_ATTR), - vChild = validChildren[tag], - firstChild = node.firstChild, - isValidChild = true; - - if (vChildren) { - isValidChild = vChildren.indexOf(tag) > -1; - - // Emoticons should always be converted - if (isEmoticon) { - isValidChild = true; + dom.traverse(node, + function(node) { + var content = ''; + const nodeType = node.nodeType; + const tag = node.nodeName.toLowerCase(); + const isCodeTag = tag === 'code'; + var vChild = validChildren[tag]; + const firstChild = node.firstChild; + var isValidChild = true; + + if (vChildren) { + isValidChild = vChildren.indexOf(tag) > -1; + + // if this tag is one of the parents allowed children + // then set this tags allowed children to whatever it + // allows, otherwise set to what the parent allows + if (!isValidChild) { + vChild = vChildren; + } } - // if this tag is one of the parents allowed children - // then set this tags allowed children to whatever it - // allows, otherwise set to what the parent allows - if (!isValidChild) { - vChild = vChildren; - } - } - - // 1 = element - if (nodeType === 1) { - // skip empty nlf elements (new lines automatically - // added after block level elements like quotes) - if (is(node, '.sceditor-nlf') && !firstChild) { - return; - } + // 1 = element + if (nodeType === 1) { + // skip empty nlf elements (new lines automatically + // added after block level elements like quotes) + if (is(node, '.sceditor-nlf') && !firstChild) { + return; + } - // don't convert iframe contents - if (tag !== 'iframe') { - content = toBBCode(node, hasCodeParent || isCodeTag, - vChild); - } + // don't convert iframe contents + if (tag !== 'iframe') { + content = toBBCode(node, + hasCodeParent || isCodeTag, + vChild); + } - // TODO: isValidChild is no longer needed. Should use - // valid children bbcodes instead by creating BBCode - // tokens like the parser. - if (isValidChild) { - // Emoticons should be converted if they have found - // their way into a code tag - if (!hasCodeParent || isEmoticon) { - if (!isCodeTag) { - // Parse inline codes first so they don't - // contain block level codes - content = handleTags(node, content, false); + // TODO: isValidChild is no longer needed. Should use + // valid children bbcodes instead by creating BBCode + // tokens like the parser. + if (isValidChild) { + // Emoticons should be converted if they have found + // their way into a code tag + if (!hasCodeParent) { + if (!isCodeTag) { + // Parse inline codes first so they don't + // contain block level codes + content = handleTags(node, content, false); + } + + content = handleTags(node, content, true); } - - content = handleTags(node, content, true); + ret += handleBlockNewlines(node, content); + } else { + ret += content; } - ret += handleBlockNewlines(node, content); - } else { - ret += content; + // 3 = text + } else if (nodeType === 3) { + ret += node.nodeValue; } - // 3 = text - } else if (nodeType === 3) { - ret += node.nodeValue; - } - }, false, true); + }, + false, + true); return ret; }; @@ -2470,7 +2706,7 @@ * Initializer * @private */ - base.init = function () { + base.init = function() { base.opts = this.opts; base.elementToBbcode = elementToBbcode; @@ -2478,11 +2714,14 @@ buildBbcodeCache(); this.commands = extend( - true, {}, defaultCommandsOverrides, this.commands + true, + {}, + defaultCommandsOverrides, + this.commands ); // Add BBCode helper methods - this.toBBCode = base.toSource; + this.toBBCode = base.toSource; this.fromBBCode = base.toHtml; }; @@ -2494,10 +2733,10 @@ * @param {boolean} [legacyAsFragment] Used by fromBBCode() method */ function toHtml(asFragment, source, legacyAsFragment) { - var parser = new BBCodeParser(base.opts.parserOptions); - var toHTML = (asFragment || legacyAsFragment) ? - parser.toHTMLFragment : - parser.toHTML; + const parser = new BBCodeParser(base.opts.parserOptions); + const toHTML = (asFragment || legacyAsFragment) ? parser.toHTMLFragment : parser.toHTML; + + editorOptions = base.opts; return toHTML(base.opts.bbcodeTrim ? source.trim() : source); } @@ -2515,11 +2754,11 @@ function toSource(asFragment, html, context, parent) { context = context || document; - var bbcode, elements; - var hasCodeParent = !!dom.closest(parent, 'code'); - var containerParent = context.createElement('div'); - var container = context.createElement('div'); - var parser = new BBCodeParser(base.opts.parserOptions); + var bbcode, elements; + const hasCodeParent = !!dom.closest(parent, 'code'); + const containerParent = context.createElement('div'); + const container = context.createElement('div'); + const parser = new BBCodeParser(base.opts.parserOptions); container.innerHTML = html; css(containerParent, 'visibility', 'hidden'); @@ -2575,7 +2814,7 @@ * @return {Object|null} * @since 2.0.0 */ - bbcodeFormat.get = function (name) { + bbcodeFormat.get = function(name) { return bbcodeHandlers[name] || null; }; @@ -2588,12 +2827,12 @@ * @return {this} * @since 2.0.0 */ - bbcodeFormat.set = function (name, bbcode) { + bbcodeFormat.set = function(name, bbcode) { if (name && bbcode) { // merge any existing command properties bbcode = extend(bbcodeHandlers[name] || {}, bbcode); - bbcode.remove = function () { + bbcode.remove = function() { delete bbcodeHandlers[name]; }; @@ -2614,7 +2853,7 @@ * @return {this|false} * @since 2.0.0 */ - bbcodeFormat.rename = function (name, newName) { + bbcodeFormat.rename = function(name, newName) { if (name in bbcodeHandlers) { bbcodeHandlers[newName] = bbcodeHandlers[name]; @@ -2631,7 +2870,7 @@ * @return {this} * @since 2.0.0 */ - bbcodeFormat.remove = function (name) { + bbcodeFormat.remove = function(name) { if (name in bbcodeHandlers) { delete bbcodeHandlers[name]; } diff --git a/src/formats/xhtml.js b/src/formats/xhtml.js deleted file mode 100644 index 296130880..000000000 --- a/src/formats/xhtml.js +++ /dev/null @@ -1,1269 +0,0 @@ -/** - * SCEditor XHTML Plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @author Sam Clarke - */ -(function (sceditor) { - 'use strict'; - - var dom = sceditor.dom; - var utils = sceditor.utils; - - var css = dom.css; - var attr = dom.attr; - var is = dom.is; - var removeAttr = dom.removeAttr; - var convertElement = dom.convertElement; - var extend = utils.extend; - var each = utils.each; - var isEmptyObject = utils.isEmptyObject; - - var getEditorCommand = sceditor.command.get; - - var defaultCommandsOverrides = { - bold: { - txtExec: ['', ''] - }, - italic: { - txtExec: ['', ''] - }, - underline: { - txtExec: ['', ''] - }, - strike: { - txtExec: ['', ''] - }, - subscript: { - txtExec: ['', ''] - }, - superscript: { - txtExec: ['', ''] - }, - left: { - txtExec: ['
', '
'] - }, - center: { - txtExec: ['
', '
'] - }, - right: { - txtExec: ['
', '
'] - }, - justify: { - txtExec: ['
', '
'] - }, - font: { - txtExec: function (caller) { - var editor = this; - - getEditorCommand('font')._dropDown( - editor, - caller, - function (font) { - editor.insertText('', ''); - } - ); - } - }, - size: { - txtExec: function (caller) { - var editor = this; - - getEditorCommand('size')._dropDown( - editor, - caller, - function (size) { - editor.insertText('', ''); - } - ); - } - }, - color: { - txtExec: function (caller) { - var editor = this; - - getEditorCommand('color')._dropDown( - editor, - caller, - function (color) { - editor.insertText('', ''); - } - ); - } - }, - bulletlist: { - txtExec: ['
  • ', '
'] - }, - orderedlist: { - txtExec: ['
  1. ', '
'] - }, - table: { - txtExec: ['
', '
'] - }, - horizontalrule: { - txtExec: ['
'] - }, - code: { - txtExec: ['', ''] - }, - image: { - txtExec: function (caller, selected) { - var editor = this; - - getEditorCommand('image')._dropDown( - editor, - caller, - selected, - function (url, width, height) { - var attrs = ''; - - if (width) { - attrs += ' width="' + width + '"'; - } - - if (height) { - attrs += ' height="' + height + '"'; - } - - editor.insertText( - '' - ); - } - ); - } - }, - email: { - txtExec: function (caller, selected) { - var editor = this; - - getEditorCommand('email')._dropDown( - editor, - caller, - function (url, text) { - editor.insertText( - '' + - (text || selected || url) + - '' - ); - } - ); - } - }, - link: { - txtExec: function (caller, selected) { - var editor = this; - - getEditorCommand('link')._dropDown( - editor, - caller, - function (url, text) { - editor.insertText( - '' + - (text || selected || url) + - '' - ); - } - ); - } - }, - quote: { - txtExec: ['
', '
'] - }, - youtube: { - txtExec: function (caller) { - var editor = this; - - getEditorCommand('youtube')._dropDown( - editor, - caller, - function (id, time) { - editor.insertText( - '' - ); - } - ); - } - }, - rtl: { - txtExec: ['
', '
'] - }, - ltr: { - txtExec: ['
', '
'] - } - }; - - /** - * XHTMLSerializer part of the XHTML plugin. - * - * @class XHTMLSerializer - * @name jQuery.sceditor.XHTMLSerializer - * @since v1.4.1 - */ - sceditor.XHTMLSerializer = function () { - var base = this; - - var opts = { - indentStr: '\t' - }; - - /** - * Array containing the output, used as it's faster - * than string concatenation in slow browsers. - * @type {Array} - * @private - */ - var outputStringBuilder = []; - - /** - * Current indention level - * @type {number} - * @private - */ - var currentIndent = 0; - - // TODO: use escape.entities - /** - * Escapes XHTML entities - * - * @param {string} str - * @return {string} - * @private - */ - function escapeEntities(str) { - var entities = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - '\xa0': ' ' - }; - - return !str ? '' : str.replace(/[&<>"\xa0]/g, function (entity) { - return entities[entity] || entity; - }); - }; - - /** - * Replace spaces including newlines with a single - * space except for non-breaking spaces - * - * @param {string} str - * @return {string} - * @private - */ - function trim(str) { - return str.replace(/[^\S\u00A0]+/g, ' '); - }; - - /** - * Serializes a node to XHTML - * - * @param {Node} node Node to serialize - * @param {boolean} onlyChildren If to only serialize the nodes - * children and not the node - * itself - * @return {string} The serialized node - * @name serialize - * @memberOf jQuery.sceditor.XHTMLSerializer.prototype - * @since v1.4.1 - */ - base.serialize = function (node, onlyChildren) { - outputStringBuilder = []; - - if (onlyChildren) { - node = node.firstChild; - - while (node) { - serializeNode(node); - node = node.nextSibling; - } - } else { - serializeNode(node); - } - - return outputStringBuilder.join(''); - }; - - /** - * Serializes a node to the outputStringBuilder - * - * @param {Node} node - * @return {void} - * @private - */ - function serializeNode(node, parentIsPre) { - switch (node.nodeType) { - case 1: // element - handleElement(node, parentIsPre); - break; - - case 3: // text - handleText(node, parentIsPre); - break; - - case 4: // cdata section - handleCdata(node); - break; - - case 8: // comment - handleComment(node); - break; - - case 9: // document - case 11: // document fragment - handleDoc(node); - break; - - // Ignored types - case 2: // attribute - case 5: // entity ref - case 6: // entity - case 7: // processing instruction - case 10: // document type - case 12: // notation - break; - } - }; - - /** - * Handles doc node - * @param {Node} node - * @return {void} - * @private - */ - function handleDoc(node) { - var child = node.firstChild; - - while (child) { - serializeNode(child); - child = child.nextSibling; - } - }; - - /** - * Handles element nodes - * @param {Node} node - * @return {void} - * @private - */ - function handleElement(node, parentIsPre) { - var child, attr, attrValue, - tagName = node.nodeName.toLowerCase(), - isIframe = tagName === 'iframe', - attrIdx = node.attributes.length, - firstChild = node.firstChild, - // pre || pre-wrap with any vendor prefix - isPre = parentIsPre || - /pre(?:\-wrap)?$/i.test(css(node, 'whiteSpace')), - selfClosing = !node.firstChild && !dom.canHaveChildren(node) && - !isIframe; - - if (is(node, '.sceditor-ignore')) { - return; - } - - output('<' + tagName, !parentIsPre && canIndent(node)); - while (attrIdx--) { - attr = node.attributes[attrIdx]; - - attrValue = attr.value; - - output(' ' + attr.name.toLowerCase() + '="' + - escapeEntities(attrValue) + '"', false); - } - output(selfClosing ? ' />' : '>', false); - - if (!isIframe) { - child = firstChild; - } - - while (child) { - currentIndent++; - - serializeNode(child, isPre); - child = child.nextSibling; - - currentIndent--; - } - - if (!selfClosing) { - output( - '', - !isPre && !isIframe && canIndent(node) && - firstChild && canIndent(firstChild) - ); - } - }; - - /** - * Handles CDATA nodes - * @param {Node} node - * @return {void} - * @private - */ - function handleCdata(node) { - output(''); - }; - - /** - * Handles comment nodes - * @param {Node} node - * @return {void} - * @private - */ - function handleComment(node) { - output(''); - }; - - /** - * Handles text nodes - * @param {Node} node - * @return {void} - * @private - */ - function handleText(node, parentIsPre) { - var text = node.nodeValue; - - if (!parentIsPre) { - text = trim(text); - } - - if (text) { - output(escapeEntities(text), !parentIsPre && canIndent(node)); - } - }; - - /** - * Adds a string to the outputStringBuilder. - * - * The string will be indented unless indent is set to boolean false. - * @param {string} str - * @param {boolean} indent - * @return {void} - * @private - */ - function output(str, indent) { - var i = currentIndent; - - if (indent !== false) { - // Don't add a new line if it's the first element - if (outputStringBuilder.length) { - outputStringBuilder.push('\n'); - } - - while (i--) { - outputStringBuilder.push(opts.indentStr); - } - } - - outputStringBuilder.push(str); - }; - - /** - * Checks if should indent the node or not - * @param {Node} node - * @return {boolean} - * @private - */ - function canIndent(node) { - var prev = node.previousSibling; - - if (node.nodeType !== 1 && prev) { - return !dom.isInline(prev); - } - - // first child of a block element - if (!prev && !dom.isInline(node.parentNode)) { - return true; - } - - return !dom.isInline(node); - }; - }; - - /** - * SCEditor XHTML plugin - * @class xhtml - * @name jQuery.sceditor.plugins.xhtml - * @since v1.4.1 - */ - function xhtmlFormat() { - var base = this; - - /** - * Tag converters cache - * @type {Object} - * @private - */ - var tagConvertersCache = {}; - - /** - * Attributes filter cache - * @type {Object} - * @private - */ - var attrsCache = {}; - - /** - * Init - * @return {void} - */ - base.init = function () { - if (!isEmptyObject(xhtmlFormat.converters || {})) { - each( - xhtmlFormat.converters, - function (idx, converter) { - each(converter.tags, function (tagname) { - if (!tagConvertersCache[tagname]) { - tagConvertersCache[tagname] = []; - } - - tagConvertersCache[tagname].push(converter); - }); - } - ); - } - - this.commands = extend(true, - {}, defaultCommandsOverrides, this.commands); - }; - - /** - * Converts the WYSIWYG content to XHTML - * - * @param {boolean} isFragment - * @param {string} html - * @param {Document} context - * @param {HTMLElement} [parent] - * @return {string} - * @memberOf jQuery.sceditor.plugins.xhtml.prototype - */ - function toSource(isFragment, html, context) { - var xhtml, - container = context.createElement('div'); - container.innerHTML = html; - - css(container, 'visibility', 'hidden'); - context.body.appendChild(container); - - convertTags(container); - removeTags(container); - removeAttribs(container); - - if (!isFragment) { - wrapInlines(container); - } - - xhtml = (new sceditor.XHTMLSerializer()).serialize(container, true); - - context.body.removeChild(container); - - return xhtml; - }; - - base.toSource = toSource.bind(null, false); - - base.fragmentToSource = toSource.bind(null, true);; - - /** - * Runs all converters for the specified tagName - * against the DOM node. - * @param {string} tagName - * @return {Node} node - * @private - */ - function convertNode(tagName, node) { - if (!tagConvertersCache[tagName]) { - return; - } - - tagConvertersCache[tagName].forEach(function (converter) { - if (converter.tags[tagName]) { - each(converter.tags[tagName], function (attr, values) { - if (!node.getAttributeNode) { - return; - } - - attr = node.getAttributeNode(attr); - - if (!attr || values && values.indexOf(attr.value) < 0) { - return; - } - - converter.conv.call(base, node); - }); - } else if (converter.conv) { - converter.conv.call(base, node); - } - }); - }; - - /** - * Converts any tags/attributes to their XHTML equivalents - * @param {Node} node - * @return {void} - * @private - */ - function convertTags(node) { - dom.traverse(node, function (node) { - var tagName = node.nodeName.toLowerCase(); - - convertNode('*', node); - convertNode(tagName, node); - }, true); - }; - - /** - * Tests if a node is empty and can be removed. - * - * @param {Node} node - * @return {boolean} - * @private - */ - function isEmpty(node, excludeBr) { - var rect, - childNodes = node.childNodes, - tagName = node.nodeName.toLowerCase(), - nodeValue = node.nodeValue, - childrenLength = childNodes.length, - allowedEmpty = xhtmlFormat.allowedEmptyTags || []; - - if (excludeBr && tagName === 'br') { - return true; - } - - if (is(node, '.sceditor-ignore')) { - return true; - } - - if (allowedEmpty.indexOf(tagName) > -1 || tagName === 'td' || - !dom.canHaveChildren(node)) { - - return false; - } - - // \S|\u00A0 = any non space char - if (nodeValue && /\S|\u00A0/.test(nodeValue)) { - return false; - } - - while (childrenLength--) { - if (!isEmpty(childNodes[childrenLength], - excludeBr && !node.previousSibling && !node.nextSibling)) { - return false; - } - } - - // Treat tags with a width and height from CSS as not empty - if (node.getBoundingClientRect && - (node.className || node.hasAttributes('style'))) { - rect = node.getBoundingClientRect(); - return !rect.width || !rect.height; - } - - return true; - }; - - /** - * Removes any tags that are not white listed or if no - * tags are white listed it will remove any tags that - * are black listed. - * - * @param {Node} rootNode - * @return {void} - * @private - */ - function removeTags(rootNode) { - dom.traverse(rootNode, function (node) { - var remove, - tagName = node.nodeName.toLowerCase(), - parentNode = node.parentNode, - nodeType = node.nodeType, - isBlock = !dom.isInline(node), - previousSibling = node.previousSibling, - nextSibling = node.nextSibling, - isTopLevel = parentNode === rootNode, - noSiblings = !previousSibling && !nextSibling, - empty = tagName !== 'iframe' && isEmpty(node, - isTopLevel && noSiblings && tagName !== 'br'), - document = node.ownerDocument, - allowedTags = xhtmlFormat.allowedTags, - firstChild = node.firstChild, - disallowedTags = xhtmlFormat.disallowedTags; - - // 3 = text node - if (nodeType === 3) { - return; - } - - if (nodeType === 4) { - tagName = '!cdata'; - } else if (tagName === '!' || nodeType === 8) { - tagName = '!comment'; - } - - if (nodeType === 1) { - // skip empty nlf elements (new lines automatically - // added after block level elements like quotes) - if (is(node, '.sceditor-nlf')) { - if (!firstChild || (node.childNodes.length === 1 && - /br/i.test(firstChild.nodeName))) { - // Mark as empty,it will be removed by the next code - empty = true; - } else { - node.classList.remove('sceditor-nlf'); - - if (!node.className) { - removeAttr(node, 'class'); - } - } - } - } - - if (empty) { - remove = true; - // 3 is text node which do not get filtered - } else if (allowedTags && allowedTags.length) { - remove = (allowedTags.indexOf(tagName) < 0); - } else if (disallowedTags && disallowedTags.length) { - remove = (disallowedTags.indexOf(tagName) > -1); - } - - if (remove) { - if (!empty) { - if (isBlock && previousSibling && - dom.isInline(previousSibling)) { - parentNode.insertBefore( - document.createTextNode(' '), node); - } - - // Insert all the childen after node - while (node.firstChild) { - parentNode.insertBefore(node.firstChild, - nextSibling); - } - - if (isBlock && nextSibling && - dom.isInline(nextSibling)) { - parentNode.insertBefore( - document.createTextNode(' '), nextSibling); - } - } - - parentNode.removeChild(node); - } - }, true); - }; - - /** - * Merges two sets of attribute filters into one - * - * @param {Object} filtersA - * @param {Object} filtersB - * @return {Object} - * @private - */ - function mergeAttribsFilters(filtersA, filtersB) { - var ret = {}; - - if (filtersA) { - ret = extend({}, ret, filtersA); - } - - if (!filtersB) { - return ret; - } - - each(filtersB, function (attrName, values) { - if (Array.isArray(values)) { - ret[attrName] = (ret[attrName] || []).concat(values); - } else if (!ret[attrName]) { - ret[attrName] = null; - } - }); - - return ret; - }; - - /** - * Wraps adjacent inline child nodes of root - * in paragraphs. - * - * @param {Node} root - * @private - */ - function wrapInlines(root) { - // Strip empty text nodes so they don't get wrapped. - dom.removeWhiteSpace(root); - - var wrapper; - var node = root.firstChild; - var next; - while (node) { - next = node.nextSibling; - - if (dom.isInline(node) && !is(node, '.sceditor-ignore')) { - if (!wrapper) { - wrapper = root.ownerDocument.createElement('p'); - node.parentNode.insertBefore(wrapper, node); - } - - wrapper.appendChild(node); - } else { - wrapper = null; - } - - node = next; - } - }; - - /** - * Removes any attributes that are not white listed or - * if no attributes are white listed it will remove - * any attributes that are black listed. - * @param {Node} node - * @return {void} - * @private - */ - function removeAttribs(node) { - var tagName, attr, attrName, attrsLength, validValues, remove, - allowedAttribs = xhtmlFormat.allowedAttribs, - isAllowed = allowedAttribs && - !isEmptyObject(allowedAttribs), - disallowedAttribs = xhtmlFormat.disallowedAttribs, - isDisallowed = disallowedAttribs && - !isEmptyObject(disallowedAttribs); - - attrsCache = {}; - - dom.traverse(node, function (node) { - if (!node.attributes) { - return; - } - - tagName = node.nodeName.toLowerCase(); - attrsLength = node.attributes.length; - - if (attrsLength) { - if (!attrsCache[tagName]) { - if (isAllowed) { - attrsCache[tagName] = mergeAttribsFilters( - allowedAttribs['*'], - allowedAttribs[tagName] - ); - } else { - attrsCache[tagName] = mergeAttribsFilters( - disallowedAttribs['*'], - disallowedAttribs[tagName] - ); - } - } - - while (attrsLength--) { - attr = node.attributes[attrsLength]; - attrName = attr.name; - validValues = attrsCache[tagName][attrName]; - remove = false; - - if (isAllowed) { - remove = validValues !== null && - (!Array.isArray(validValues) || - validValues.indexOf(attr.value) < 0); - } else if (isDisallowed) { - remove = validValues === null || - (Array.isArray(validValues) && - validValues.indexOf(attr.value) > -1); - } - - if (remove) { - node.removeAttribute(attrName); - } - } - } - }); - }; - }; - - /** - * Tag conveters, a converter is applied to all - * tags that match the criteria. - * @type {Array} - * @name jQuery.sceditor.plugins.xhtml.converters - * @since v1.4.1 - */ - xhtmlFormat.converters = [ - { - tags: { - '*': { - width: null - } - }, - conv: function (node) { - css(node, 'width', attr(node, 'width')); - removeAttr(node, 'width'); - } - }, - { - tags: { - '*': { - height: null - } - }, - conv: function (node) { - css(node, 'height', attr(node, 'height')); - removeAttr(node, 'height'); - } - }, - { - tags: { - 'li': { - value: null - } - }, - conv: function (node) { - removeAttr(node, 'value'); - } - }, - { - tags: { - '*': { - text: null - } - }, - conv: function (node) { - css(node, 'color', attr(node, 'text')); - removeAttr(node, 'text'); - } - }, - { - tags: { - '*': { - color: null - } - }, - conv: function (node) { - css(node, 'color', attr(node, 'color')); - removeAttr(node, 'color'); - } - }, - { - tags: { - '*': { - face: null - } - }, - conv: function (node) { - css(node, 'fontFamily', attr(node, 'face')); - removeAttr(node, 'face'); - } - }, - { - tags: { - '*': { - align: null - } - }, - conv: function (node) { - css(node, 'textAlign', attr(node, 'align')); - removeAttr(node, 'align'); - } - }, - { - tags: { - '*': { - border: null - } - }, - conv: function (node) { - css(node, 'borderWidth', attr(node, 'border')); - removeAttr(node, 'border'); - } - }, - { - tags: { - applet: { - name: null - }, - img: { - name: null - }, - layer: { - name: null - }, - map: { - name: null - }, - object: { - name: null - }, - param: { - name: null - } - }, - conv: function (node) { - if (!attr(node, 'id')) { - attr(node, 'id', attr(node, 'name')); - } - - removeAttr(node, 'name'); - } - }, - { - tags: { - '*': { - vspace: null - } - }, - conv: function (node) { - css(node, 'marginTop', attr(node, 'vspace') - 0); - css(node, 'marginBottom', attr(node, 'vspace') - 0); - removeAttr(node, 'vspace'); - } - }, - { - tags: { - '*': { - hspace: null - } - }, - conv: function (node) { - css(node, 'marginLeft', attr(node, 'hspace') - 0); - css(node, 'marginRight', attr(node, 'hspace') - 0); - removeAttr(node, 'hspace'); - } - }, - { - tags: { - 'hr': { - noshade: null - } - }, - conv: function (node) { - css(node, 'borderStyle', 'solid'); - removeAttr(node, 'noshade'); - } - }, - { - tags: { - '*': { - nowrap: null - } - }, - conv: function (node) { - css(node, 'whiteSpace', 'nowrap'); - removeAttr(node, 'nowrap'); - } - }, - { - tags: { - big: null - }, - conv: function (node) { - css(convertElement(node, 'span'), 'fontSize', 'larger'); - } - }, - { - tags: { - small: null - }, - conv: function (node) { - css(convertElement(node, 'span'), 'fontSize', 'smaller'); - } - }, - { - tags: { - b: null - }, - conv: function (node) { - convertElement(node, 'strong'); - } - }, - { - tags: { - u: null - }, - conv: function (node) { - css(convertElement(node, 'span'), 'textDecoration', - 'underline'); - } - }, - { - tags: { - s: null, - strike: null - }, - conv: function (node) { - css(convertElement(node, 'span'), 'textDecoration', - 'line-through'); - } - }, - { - tags: { - dir: null - }, - conv: function (node) { - convertElement(node, 'ul'); - } - }, - { - tags: { - center: null - }, - conv: function (node) { - css(convertElement(node, 'div'), 'textAlign', 'center'); - } - }, - { - tags: { - font: { - size: null - } - }, - conv: function (node) { - css(node, 'fontSize', css(node, 'fontSize')); - removeAttr(node, 'size'); - } - }, - { - tags: { - font: null - }, - conv: function (node) { - // All it's attributes will be converted - // by the attribute converters - convertElement(node, 'span'); - } - }, - { - tags: { - '*': { - type: ['_moz'] - } - }, - conv: function (node) { - removeAttr(node, 'type'); - } - }, - { - tags: { - '*': { - '_moz_dirty': null - } - }, - conv: function (node) { - removeAttr(node, '_moz_dirty'); - } - }, - { - tags: { - '*': { - '_moz_editor_bogus_node': null - } - }, - conv: function (node) { - node.parentNode.removeChild(node); - } - }, - { - tags: { - '*': { - 'data-sce-target': null - } - }, - conv: function (node) { - var rel = attr(node, 'rel') || ''; - var target = attr(node, 'data-sce-target'); - - // Only allow the value _blank and only on links - if (target === '_blank' && is(node, 'a')) { - if (!/(^|\s)noopener(\s|$)/.test(rel)) { - attr(node, 'rel', 'noopener' + (rel ? ' ' + rel : '')); - } - - attr(node, 'target', target); - } - - - removeAttr(node, 'data-sce-target'); - } - }, - { - tags: { - code: null - }, - conv: function (node) { - var node, nodes = node.getElementsByTagName('div'); - while ((node = nodes[0])) { - node.style.display = 'block'; - convertElement(node, 'span'); - } - } - } - ]; - - /** - * Allowed attributes map. - * - * To allow an attribute for all tags use * as the tag name. - * - * Leave empty or null to allow all attributes. (the disallow - * list will be used to filter them instead) - * @type {Object} - * @name jQuery.sceditor.plugins.xhtml.allowedAttribs - * @since v1.4.1 - */ - xhtmlFormat.allowedAttribs = {}; - - /** - * Attributes that are not allowed. - * - * Only used if allowed attributes is null or empty. - * @type {Object} - * @name jQuery.sceditor.plugins.xhtml.disallowedAttribs - * @since v1.4.1 - */ - xhtmlFormat.disallowedAttribs = {}; - - /** - * Array containing all the allowed tags. - * - * If null or empty all tags will be allowed. - * @type {Array} - * @name jQuery.sceditor.plugins.xhtml.allowedTags - * @since v1.4.1 - */ - xhtmlFormat.allowedTags = []; - - /** - * Array containing all the disallowed tags. - * - * Only used if allowed tags is null or empty. - * @type {Array} - * @name jQuery.sceditor.plugins.xhtml.disallowedTags - * @since v1.4.1 - */ - xhtmlFormat.disallowedTags = []; - - /** - * Array containing tags which should not be removed when empty. - * - * @type {Array} - * @name jQuery.sceditor.plugins.xhtml.allowedEmptyTags - * @since v2.0.0 - */ - xhtmlFormat.allowedEmptyTags = []; - - sceditor.formats.xhtml = xhtmlFormat; -}(sceditor)); diff --git a/src/icons/fontawesome.js b/src/icons/fontawesome.js new file mode 100644 index 000000000..8486fdd46 --- /dev/null +++ b/src/icons/fontawesome.js @@ -0,0 +1,115 @@ +/** + * SCEditor SVG fontawesome plugin + * http://www.sceditor.com/ + * + * Copyright (C) 2017, Sam Clarke (samclarke.com) + * + * SCEditor is licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * @author Sam Clarke + */ +(function(document, sceditor) { + + + var dom = sceditor.dom; + + /* eslint max-len: off*/ + var icons = { + 'albums': '', + 'bulletlist': '', + 'center': '', + 'code': '', + 'color': + '', + 'copy': '', + 'cut': '', + 'email': '', + 'emojis': '', + 'extensions': '', + 'font': + '', + 'format': '', + 'grip': + '', + 'mark': '', + 'horizontalrule': '', + 'image': '', + 'indent': '', + 'italic': '', + 'justify': '', + 'left': '', + 'link': '', + 'maximize': '', + 'media': '', + 'orderedlist': '', + 'outdent': '', + 'paste': '', + 'pastetext': '', + 'quote': '', + 'redo': '', + 'removeformat': '', + 'reply': '', + 'right': '', + 'size': + '', + 'source': '', + 'strike': '', + 'table': '', + 'underline': '', + 'undo': '', + 'unlink': '', + 'vimeo': '', + 'instagram': '', + 'facebook': '', + 'youtube': '' + }; + + sceditor.icons.fontawesome = function() { + var nodes = {}; + var colorPath; + + return { + create: function(command) { + if (command in icons) { + nodes[command] = sceditor.dom.parseHTML( + icons[command] + ).firstChild; + + if (command === 'color') { + colorPath = nodes[command].querySelector('.sce-color'); + } + } + + return nodes[command]; + }, + update: function(isSourceMode, currentNode) { + if (colorPath) { + let color = 'inherit'; + + if (!isSourceMode && currentNode) { + color = currentNode.ownerDocument + .queryCommandValue('forecolor'); + } + + dom.css(colorPath, 'color', color); + } + }, + rtl: function(isRtl) { + const gripNode = nodes.grip; + + if (gripNode) { + const transform = isRtl ? 'scaleX(-1)' : ''; + + dom.css(gripNode, 'transform', transform); + dom.css(gripNode, 'msTransform', transform); + dom.css(gripNode, 'webkitTransform', transform); + } + } + }; + }; + + sceditor.icons.fontawesome.icons = icons; +})(document, sceditor); diff --git a/src/icons/material.js b/src/icons/material.js deleted file mode 100644 index acad57230..000000000 --- a/src/icons/material.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * SCEditor SVG material icons plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @author Sam Clarke - */ -(function (document, sceditor) { - 'use strict'; - - var dom = sceditor.dom; - - /** - * Material icons by Google (Apache license) - * https://github.com/google/material-design-icons/blob/master/LICENSE - * - * Extra icons by materialdesignicons.com and contributors (MIT license) - * https://github.com/Templarian/MaterialDesign-SVG/blob/master/LICENSE - */ - /* eslint max-len: off*/ - var icons = { - 'bold': '', - 'bulletlist': '', - 'center': '', - // Cody @XT3000 - https://materialdesignicons.com/ - 'code': '', - 'color': '', - 'copy': '', - 'cut': '', - 'date': '', - 'email': '', - 'emoticon': '', - // JapanYoshi @japanyoshilol - https://materialdesignicons.com/ - 'font': '', - 'format': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'grip': '', - // Sam Clarke @samclarke - 'horizontalrule': '', - 'image': '', - 'indent': '', - 'italic': '', - 'justify': ' ', - 'left': ' ', - 'link': '', - 'ltr': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'maximize': '', - 'orderedlist': '', - 'outdent': '', - 'paste': '', - 'pastetext': '', - 'print': '', - 'quote': '', - 'redo': '', - 'removeformat': '', - 'right': '', - 'rtl': '', - 'size': '', - 'source': '', - 'strike': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'subscript': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'superscript': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'table': '', - 'time': '', - 'underline': '', - 'undo': '', - // Austin Andrews @Templarian - https://materialdesignicons.com/ - 'unlink': '', - 'youtube': '' - }; - - sceditor.icons.material = function () { - var nodes = {}; - - var colorPath; - - return { - create: function (command) { - if (command in icons) { - // Using viewbox="1 1 22 22" to trim off the 1 unit border - // around the SVG icons. - // Default is viewbox="0 0 24 24" - nodes[command] = sceditor.dom.parseHTML( - '' + - icons[command] + - '' - ).firstChild; - - if (command === 'color') { - colorPath = nodes[command].querySelector('.sce-color'); - } - } - - return nodes[command]; - }, - update: function (isSourceMode, currentNode) { - if (colorPath) { - var color = 'inherit'; - - if (!isSourceMode && currentNode) { - color = currentNode.ownerDocument - .queryCommandValue('forecolor'); - } - - dom.css(colorPath, 'fill', color); - } - }, - rtl: function (isRtl) { - var gripNode = nodes.grip; - - if (gripNode) { - var transform = isRtl ? 'scaleX(-1)' : ''; - - dom.css(gripNode, 'transform', transform); - dom.css(gripNode, 'msTransform', transform); - dom.css(gripNode, 'webkitTransform', transform); - } - } - }; - }; - - sceditor.icons.material.icons = icons; -})(document, sceditor); diff --git a/src/icons/monocons.js b/src/icons/monocons.js deleted file mode 100644 index ed027d7e9..000000000 --- a/src/icons/monocons.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * SCEditor SVG monocons plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @author Sam Clarke - */ -(function (document, sceditor) { - 'use strict'; - - var dom = sceditor.dom; - - /* eslint max-len: off*/ - var icons = { - 'bold': 'B', - 'bulletlist': '', - 'center': '', - 'code': '', - 'color': 'A', - 'copy': '', - 'cut': '', - 'date': '', - 'email': '', - 'emoticon': '', - 'font': '', - 'format': '', - 'grip': '', - 'horizontalrule': '', - 'image': '', - 'indent': '', - 'italic': 'i', - 'justify': '', - 'left': '', - 'link': '', - 'ltr': '', - 'maximize': '', - 'orderedlist': '', - 'outdent': '', - 'paste': '', - 'pastetext': '', - 'print': '', - 'quote': '', - 'redo': '', - 'removeformat': '', - 'right': '', - 'rtl': '', - 'size': '', - 'source': '', - 'strike': 'S', - 'subscript': '', - 'superscript': '', - 'table': '', - 'time': '', - 'underline': 'U', - 'undo': '', - 'unlink': '', - 'youtube': '' - }; - - sceditor.icons.monocons = function () { - var nodes = {}; - var colorPath; - - return { - create: function (command) { - if (command in icons) { - nodes[command] = sceditor.dom.parseHTML( - '' + - icons[command] + - '' - ).firstChild; - - if (command === 'color') { - colorPath = nodes[command].querySelector('.sce-color'); - } - } - - return nodes[command]; - }, - update: function (isSourceMode, currentNode) { - if (colorPath) { - var color = 'inherit'; - - if (!isSourceMode && currentNode) { - color = currentNode.ownerDocument - .queryCommandValue('forecolor'); - } - - dom.css(colorPath, 'fill', color); - } - }, - rtl: function (isRtl) { - var gripNode = nodes.grip; - - if (gripNode) { - var transform = isRtl ? 'scaleX(-1)' : ''; - - dom.css(gripNode, 'transform', transform); - dom.css(gripNode, 'msTransform', transform); - dom.css(gripNode, 'webkitTransform', transform); - } - } - }; - }; - - sceditor.icons.monocons.icons = icons; -})(document, sceditor); diff --git a/src/jquery.sceditor.js b/src/jquery.sceditor.js deleted file mode 100644 index 6f463421a..000000000 --- a/src/jquery.sceditor.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * SCEditor - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @fileoverview SCEditor - A lightweight WYSIWYG BBCode and HTML editor - * @author Sam Clarke - * @requires jQuery - */ - -import $ from 'jquery'; -import './sceditor.js'; - - -// For backwards compatibility -$.sceditor = window.sceditor; - -/** - * Creates an instance of sceditor on all textareas - * matched by the jQuery selector. - * - * If options is set to "state" it will return bool value - * indicating if the editor has been initialised on the - * matched textarea(s). If there is only one textarea - * it will return the bool value for that textarea. - * If more than one textarea is matched it will - * return an array of bool values for each textarea. - * - * If options is set to "instance" it will return the - * current editor instance for the textarea(s). Like the - * state option, if only one textarea is matched this will - * return just the instance for that textarea. If more than - * one textarea is matched it will return an array of - * instances each textarea. - * - * @param {Object|string} [options] Should either be an Object of options or - * the strings "state" or "instance" - * @return {this|Array|Array|SCEditor|boolean} - */ -$.fn.sceditor = function (options) { - var instance; - var ret = []; - - this.each(function () { - instance = this._sceditor; - - // Add state of instance to ret if that is what options is set to - if (options === 'state') { - ret.push(!!instance); - } else if (options === 'instance') { - ret.push(instance); - } else if (!instance) { - $.sceditor.create(this, options); - } - }); - - // If nothing in the ret array then must be init so return this - if (!ret.length) { - return this; - } - - return ret.length === 1 ? ret[0] : ret; -}; diff --git a/src/lib/PluginManager.js b/src/lib/PluginManager.js index 828823265..fd709d609 100644 --- a/src/lib/PluginManager.js +++ b/src/lib/PluginManager.js @@ -31,7 +31,7 @@ export default function PluginManager(thisObj) { * @private */ var formatSignalName = function (signal) { - return 'signal' + signal.charAt(0).toUpperCase() + signal.slice(1); + return `signal${signal.charAt(0).toUpperCase()}${signal.slice(1)}`; }; /** @@ -47,8 +47,8 @@ export default function PluginManager(thisObj) { var callHandlers = function (args, returnAtFirst) { args = [].slice.call(args); - var idx, ret, - signal = formatSignalName(args.shift()); + var idx, ret; + const signal = formatSignalName(args.shift()); for (idx = 0; idx < registeredPlugins.length; idx++) { if (signal in registeredPlugins[idx]) { @@ -141,7 +141,7 @@ export default function PluginManager(thisObj) { */ base.isRegistered = function (plugin) { if (base.exists(plugin)) { - var idx = registeredPlugins.length; + let idx = registeredPlugins.length; while (idx--) { if (registeredPlugins[idx] instanceof plugins[plugin]) { diff --git a/src/lib/RangeHelper.js b/src/lib/RangeHelper.js index 83c8aa901..92f9bd026 100644 --- a/src/lib/RangeHelper.js +++ b/src/lib/RangeHelper.js @@ -95,8 +95,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.insertHTML = function (html, endHTML) { - var node, div, - range = base.selectedRange(); + const range = base.selectedRange(); if (!range) { return false; @@ -106,8 +105,8 @@ export default function RangeHelper(win, d, sanitize) { html += base.selectedHtml() + endHTML; } - div = dom.createElement('p', {}, doc); - node = doc.createDocumentFragment(); + const div = dom.createElement('p', {}, doc); + const node = doc.createDocumentFragment(); div.innerHTML = sanitize(html); while (div.firstChild) { @@ -173,7 +172,7 @@ export default function RangeHelper(win, d, sanitize) { dom.appendChild(lastChild, _createMarker(endMarker)); if (returnHtml) { - var div = dom.createElement('div'); + const div = dom.createElement('div'); dom.appendChild(div, frag); return div.innerHTML; @@ -199,11 +198,11 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.insertNode = function (node, endNode) { - var first, last, - input = _prepareInput(node, endNode), - range = base.selectedRange(), - parent = range.commonAncestorContainer, - emptyNodes = []; + var first, last; + const input = _prepareInput(node, endNode); + const range = base.selectedRange(); + const parent = range.commonAncestorContainer; + var emptyNodes = []; if (!input) { return false; @@ -260,7 +259,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.cloneSelected = function () { - var range = base.selectedRange(); + const range = base.selectedRange(); if (range) { return range.cloneRange(); @@ -276,8 +275,8 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.selectedRange = function () { - var range, firstChild, - sel = win.getSelection(); + var range, firstChild; + const sel = win.getSelection(); if (!sel) { return; @@ -316,7 +315,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.hasSelection = function () { - var sel = win.getSelection(); + const sel = win.getSelection(); return sel && sel.rangeCount > 0; }; @@ -330,8 +329,8 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.selectedHtml = function () { - var div, - range = base.selectedRange(); + var div; + const range = base.selectedRange(); if (range) { div = dom.createElement('p', {}, doc); @@ -352,7 +351,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.parentNode = function () { - var range = base.selectedRange(); + const range = base.selectedRange(); if (range) { return range.commonAncestorContainer; @@ -403,8 +402,8 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.insertNodeAt = function (start, node) { - var currentRange = base.selectedRange(), - range = base.cloneSelected(); + const currentRange = base.selectedRange(); + const range = base.cloneSelected(); if (!range) { return false; @@ -428,7 +427,7 @@ export default function RangeHelper(win, d, sanitize) { _createMarker = function (id) { base.removeMarker(id); - var marker = dom.createElement('span', { + const marker = dom.createElement('span', { id: id, className: 'sceditor-selection sceditor-ignore', style: 'display:none;line-height:0' @@ -449,8 +448,8 @@ export default function RangeHelper(win, d, sanitize) { * @name insertMarkers */ base.insertMarkers = function () { - var currentRange = base.selectedRange(); - var startNode = _createMarker(startMarker); + const currentRange = base.selectedRange(); + const startNode = _createMarker(startMarker); base.removeMarkers(); base.insertNodeAt(true, startNode); @@ -487,7 +486,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.removeMarker = function (id) { - var marker = base.getMarker(id); + const marker = base.getMarker(id); if (marker) { dom.remove(marker); @@ -527,8 +526,8 @@ export default function RangeHelper(win, d, sanitize) { */ base.selectRange = function (range) { var lastChild; - var sel = win.getSelection(); - var container = range.endContainer; + const sel = win.getSelection(); + const container = range.endContainer; // Check if cursor is set after a BR when the BR is the only // child of the parent. In Firefox this causes a line break @@ -542,7 +541,7 @@ export default function RangeHelper(win, d, sanitize) { } if (dom.is(lastChild, 'br')) { - var rng = doc.createRange(); + const rng = doc.createRange(); rng.setEndAfter(lastChild); rng.collapse(false); @@ -568,9 +567,9 @@ export default function RangeHelper(win, d, sanitize) { */ base.restoreRange = function () { var isCollapsed, - range = base.selectedRange(), - start = base.getMarker(startMarker), - end = base.getMarker(endMarker); + range = base.selectedRange(); + const start = base.getMarker(startMarker); + const end = base.getMarker(endMarker); if (!start || !end || !range) { return false; @@ -601,8 +600,8 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.selectOuterText = function (left, right) { - var start, end, - range = base.cloneSelected(); + var start, end; + const range = base.cloneSelected(); if (!range) { return false; @@ -631,7 +630,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.getOuterText = function (before, length) { - var range = base.cloneSelected(); + const range = base.cloneSelected(); if (!range) { return ''; @@ -678,12 +677,12 @@ export default function RangeHelper(win, d, sanitize) { } var outerText, match, matchPos, startIndex, - leftLen, charsLeft, keyword, keywordLen, - whitespaceRegex = '(^|[\\s\xA0\u2002\u2003\u2009])', - keywordIdx = keywords.length, - whitespaceLen = requireWhitespace ? 1 : 0, - maxKeyLen = longestKeyword || - keywords[keywordIdx - 1][0].length; + leftLen, charsLeft, keyword, keywordLen; + const whitespaceRegex = '(^|[\\s\xA0\u2002\u2003\u2009])'; + var keywordIdx = keywords.length; + const whitespaceLen = requireWhitespace ? 1 : 0; + var maxKeyLen = longestKeyword || + keywords[keywordIdx - 1][0].length; if (requireWhitespace) { maxKeyLen++; @@ -779,7 +778,7 @@ export default function RangeHelper(win, d, sanitize) { * @memberOf RangeHelper.prototype */ base.clear = function () { - var sel = win.getSelection(); + const sel = win.getSelection(); if (sel) { if (sel.removeAllRanges) { diff --git a/src/lib/SCEditor.js b/src/lib/SCEditor.js index 206b6c66b..a72dcbb91 100644 --- a/src/lib/SCEditor.js +++ b/src/lib/SCEditor.js @@ -7,7 +7,6 @@ import RangeHelper from './RangeHelper.js'; import _tmpl from './templates.js'; import * as escape from './escape.js'; import * as browser from './browser.js'; -import * as emoticons from './emoticons.js'; import DOMPurify from 'dompurify'; var globalWin = window; @@ -131,6 +130,8 @@ export default function SCEditor(original, userOptions) { */ var sourceEditor; + var footer; + /** * The current dropdown * @@ -158,14 +159,6 @@ export default function SCEditor(original, userOptions) { */ var locale; - /** - * Stores a cache of preloaded images - * - * @private - * @type {Array.} - */ - var preLoadCache = []; - /** * The editors rangeHelper instance * @@ -206,6 +199,8 @@ export default function SCEditor(original, userOptions) { */ var currentBlockNode; + var backSpaceHandled; + /** * The current node selection/caret * @@ -292,15 +287,6 @@ export default function SCEditor(original, userOptions) { */ var pasteContentFragment; - /** - * All the emoticons from dropdown, more and hidden combined - * and with the emoticons root set - * - * @type {!Object} - * @private - */ - var allEmoticons = {}; - /** * Current icon set if any * @@ -314,7 +300,6 @@ export default function SCEditor(original, userOptions) { * @private */ var init, - replaceEmoticons, handleCommand, initEditor, initLocale, @@ -322,7 +307,6 @@ export default function SCEditor(original, userOptions) { initOptions, initEvents, initResize, - initEmoticons, handlePasteEvt, handleCutCopyEvt, handlePasteData, @@ -334,7 +318,6 @@ export default function SCEditor(original, userOptions) { handleComposition, handleEvent, handleDocumentClick, - loadScripts, updateToolBar, updateActiveButtons, sourceEditorSelectedText, @@ -342,8 +325,6 @@ export default function SCEditor(original, userOptions) { checkSelectionChanged, checkNodeChanged, autofocus, - emoticonsKeyPress, - emoticonsCheckWhitespace, currentStyledBlockNode, triggerValueChanged, valueChangedBlur, @@ -368,13 +349,14 @@ export default function SCEditor(original, userOptions) { true, {}, defaultOptions, userOptions ); - // Don't deep extend emoticons (fixes #565) - base.opts.emoticons = userOptions.emoticons || defaultOptions.emoticons; - if (!Array.isArray(options.allowedIframeUrls)) { options.allowedIframeUrls = []; } - options.allowedIframeUrls.push('https://www.youtube-nocookie.com/embed/'); + + options.allowedIframeUrls.push('https://youtube.com/embed/'); + options.allowedIframeUrls.push('https://player.vimeo.com/video/'); + options.allowedIframeUrls.push('https://www.instagram.com/p/'); + options.allowedIframeUrls.push('https://www.facebook.com/plugins/'); // Create new instance of DOMPurify for each editor instance so can // have different allowed iframe URLs @@ -384,13 +366,13 @@ export default function SCEditor(original, userOptions) { // Allow iframes for things like YouTube, see: // https://github.com/cure53/DOMPurify/issues/340#issuecomment-670758980 domPurify.addHook('uponSanitizeElement', function (node, data) { - var allowedUrls = options.allowedIframeUrls; + const allowedUrls = options.allowedIframeUrls; if (data.tagName === 'iframe') { - var src = dom.attr(node, 'src') || ''; + const src = dom.attr(node, 'src') || ''; - for (var i = 0; i < allowedUrls.length; i++) { - var url = allowedUrls[i]; + for (let i = 0; i < allowedUrls.length; i++) { + const url = allowedUrls[i]; if (utils.isString(url) && src.substr(0, url.length) === url) { return; @@ -435,51 +417,6 @@ export default function SCEditor(original, userOptions) { }); }; - /** - * Loads a JavaScript file and returns a Promise for when it is loaded - */ - const loadScript = src => { - return new Promise((resolve, reject) => { - const script = document.createElement('script'); - script.type = 'text/javascript'; - script.onload = resolve; - script.onerror = reject; - script.src = src; - document.head.append(script); - }); - }; - - /** - * Loads all scripts - * @private - */ - loadScripts = function () { - var promises = []; - - // Load format script - promises.push( - loadScript(`../${options.basePath}/formats/${options.format}.js`)); - - // load plugins scripts - if (options.plugins) { - (options.plugins || '').split(',').forEach(function (plugin) { - var src = `../${options.basePath}/plugins/${plugin.trim()}.js`; - promises.push( - loadScript(src)); - }); - } - - // load icons script - if (options.icons) { - promises.push( - loadScript(`../${options.basePath}/icons/${options.icons}.js`)); - } - - Promise.all(promises).then(() => { - init(); - }).catch(() => console.error('Something went wrong.')); - }; - /** * Creates the editor iframe and textarea * @private @@ -493,7 +430,7 @@ export default function SCEditor(original, userOptions) { } editorContainer = dom.createElement('div', { - className: 'sceditor-container' + className: 'sceditor-container card' }); dom.insertBefore(editorContainer, original); @@ -502,7 +439,7 @@ export default function SCEditor(original, userOptions) { isRequired = original.required; original.required = false; - var FormatCtor = SCEditor.formats[options.format]; + const FormatCtor = SCEditor.formats[options.format]; format = FormatCtor ? new FormatCtor() : {}; /* * Plugins should be initialized before the formatters since @@ -519,7 +456,6 @@ export default function SCEditor(original, userOptions) { } // create the editor - initEmoticons(); initToolBar(); initEditor(); initOptions(); @@ -586,6 +522,15 @@ export default function SCEditor(original, userOptions) { allowfullscreen: true }); + footer = dom.createElement('div'); + dom.addClass(footer, 'card-footer'); + dom.addClass(footer, 'text-body-secondary'); + dom.addClass(footer, 'text-end'); + dom.addClass(footer, 'small'); + dom.addClass(footer, 'p-2'); + + footer.appendChild(dom.parseHTML(base._('Characters remaining:') + '' + '')); + /* * This needs to be done right after they are created because, * for any reason, the user may not want the value to be tinkered @@ -607,9 +552,12 @@ export default function SCEditor(original, userOptions) { dom.attr(wysiwygEditor, 'src', 'about:blank'); } + dom.attr(sourceEditor, 'title', 'source'); + // Add the editor to the container dom.appendChild(editorContainer, wysiwygEditor); dom.appendChild(editorContainer, sourceEditor); + dom.appendChild(editorContainer, footer); // TODO: make this optional somehow base.dimensions( @@ -617,17 +565,22 @@ export default function SCEditor(original, userOptions) { options.height || dom.height(original) ); - // Add ios to HTML so can apply CSS fix to only it - var className = browser.ios ? ' ios' : ''; - wysiwygDocument = wysiwygEditor.contentDocument; wysiwygDocument.open(); + + var styles = ''; + + options.styles.forEach((style) => { + styles += _tmpl('style', {style: style}); + }); + wysiwygDocument.write(_tmpl('html', { - attrs: ' class="' + className + '"', spellcheck: options.spellcheck ? '' : 'spellcheck="false"', charset: options.charset, - style: options.style + themeMode: options.themeMode, + styles: styles })); + wysiwygDocument.close(); wysiwygBody = wysiwygDocument.body; @@ -688,7 +641,6 @@ export default function SCEditor(original, userOptions) { } dom.attr(editorContainer, 'id', options.id); - base.emoticons(options.emoticonsEnabled); }; /** @@ -696,11 +648,10 @@ export default function SCEditor(original, userOptions) { * @private */ initEvents = function () { - var form = original.form; - var compositionEvents = 'compositionstart compositionend'; - var eventsToForward = - 'keydown keyup keypress focus blur contextmenu input'; - var checkSelectionEvents = 'onselectionchange' in wysiwygDocument ? + const form = original.form; + const compositionEvents = 'compositionstart compositionend'; + const eventsToForward = 'keydown keyup keypress focus blur contextmenu input'; + const checkSelectionEvents = 'onselectionchange' in wysiwygDocument ? 'selectionchange' : 'keyup focus blur contextmenu mouseup touchend click'; @@ -725,10 +676,6 @@ export default function SCEditor(original, userOptions) { dom.on(wysiwygBody, checkSelectionEvents, checkSelectionChanged); dom.on(wysiwygBody, eventsToForward, handleEvent); - if (options.emoticonsCompat && globalWin.getSelection) { - dom.on(wysiwygBody, 'keyup', emoticonsCheckWhitespace); - } - dom.on(wysiwygBody, 'blur', function () { if (!base.val()) { dom.addClass(wysiwygBody, 'placeholder'); @@ -766,11 +713,11 @@ export default function SCEditor(original, userOptions) { initToolBar = function () { var group, commands = base.commands, - exclude = (options.toolbarExclude || '').split(','), - groups = options.toolbar.split('|'); + exclude = (options.toolbarExclude || '').split(','); + const groups = options.toolbar.split('|'); toolbar = dom.createElement('div', { - className: 'sceditor-toolbar', + className: 'card-header btn-toolbar', unselectable: 'on' }); @@ -780,12 +727,12 @@ export default function SCEditor(original, userOptions) { utils.each(groups, function (_, menuItems) { group = dom.createElement('div', { - className: 'sceditor-group' + className: 'btn-group btn-group-sm m-1' }); utils.each(menuItems.split(','), function (_, commandName) { var button, shortcut, - command = commands[commandName]; + command = commands[commandName]; // The commandName must be a valid command and not excluded if (!command || exclude.indexOf(commandName) > -1) { @@ -794,22 +741,26 @@ export default function SCEditor(original, userOptions) { shortcut = command.shortcut; button = _tmpl('toolbarButton', { - name: commandName, - dispName: base._(command.name || - command.tooltip || commandName) + name: commandName }, true).firstChild; + if (commandName === 'source') { + button.classList.add('btn-secondary'); + } else { + button.classList.add('btn-primary'); + } + if (icons && icons.create) { - var icon = icons.create(commandName); + const icon = icons.create(commandName); if (icon) { dom.insertBefore(icons.create(commandName), button.firstChild); - dom.addClass(button, 'has-icon'); } } button._sceTxtMode = !!command.txtExec; button._sceWysiwygMode = !!command.exec; + dom.toggleClass(button, 'disabled', !command.exec); dom.on(button, 'click', function (e) { if (!dom.hasClass(button, 'disabled')) { @@ -869,26 +820,21 @@ export default function SCEditor(original, userOptions) { */ initResize = function () { var minHeight, maxHeight, minWidth, maxWidth, - mouseMoveFunc, mouseUpFunc, - grip = dom.createElement('div', { - className: 'sceditor-grip' - }), - // Cover is used to cover the editor iframe so document - // still gets mouse move events - cover = dom.createElement('div', { - className: 'sceditor-resize-cover' - }), - moveEvents = 'touchmove mousemove', + mouseMoveFunc, mouseUpFunc; + const grip = dom.createElement('div', { + className: 'sceditor-grip' + }); + var moveEvents = 'touchmove mousemove', endEvents = 'touchcancel touchend mouseup', startX = 0, startY = 0, newX = 0, newY = 0, startWidth = 0, - startHeight = 0, - origWidth = dom.width(editorContainer), - origHeight = dom.height(editorContainer), - isDragging = false, + startHeight = 0; + const origWidth = dom.width(editorContainer); + const origHeight = dom.height(editorContainer); + var isDragging = false, rtl = base.rtl(); minHeight = options.resizeMinHeight || origHeight / 1.5; @@ -946,7 +892,6 @@ export default function SCEditor(original, userOptions) { isDragging = false; - dom.hide(cover); dom.removeClass(editorContainer, 'resizing'); dom.off(globalDoc, moveEvents, mouseMoveFunc); dom.off(globalDoc, endEvents, mouseUpFunc); @@ -955,16 +900,14 @@ export default function SCEditor(original, userOptions) { }; if (icons && icons.create) { - var icon = icons.create('grip'); + const icon = icons.create('grip'); if (icon) { dom.appendChild(grip, icon); - dom.addClass(grip, 'has-icon'); } } + dom.appendChild(editorContainer, footer); dom.appendChild(editorContainer, grip); - dom.appendChild(editorContainer, cover); - dom.hide(cover); dom.on(grip, 'touchstart mousedown', function (e) { // iOS uses window.event @@ -982,7 +925,6 @@ export default function SCEditor(original, userOptions) { isDragging = true; dom.addClass(editorContainer, 'resizing'); - dom.show(cover); dom.on(globalDoc, moveEvents, mouseMoveFunc); dom.on(globalDoc, endEvents, mouseUpFunc); @@ -990,37 +932,6 @@ export default function SCEditor(original, userOptions) { }); }; - /** - * Prefixes and preloads the emoticon images - * @private - */ - initEmoticons = function () { - var emoticons = options.emoticons; - var root = options.emoticonsRoot || ''; - - if (emoticons) { - allEmoticons = utils.extend( - {}, emoticons.more, emoticons.dropdown, emoticons.hidden - ); - } - - utils.each(allEmoticons, function (key, url) { - allEmoticons[key] = _tmpl('emoticon', { - key: key, - // Prefix emoticon root to emoticon urls - url: root + (url.url || url), - tooltip: url.tooltip || key - }); - - // Preload the emoticon - if (options.emoticonsEnabled) { - preLoadCache.push(dom.createElement('img', { - src: root + (url.url || url) - })); - } - }); - }; - /** * Autofocus the editor * @private @@ -1135,7 +1046,7 @@ export default function SCEditor(original, userOptions) { * @return {this} */ base.rtl = function (rtl) { - var dir = rtl ? 'rtl' : 'ltr'; + const dir = rtl ? 'rtl' : 'ltr'; if (typeof rtl !== 'boolean') { return dom.attr(sourceEditor, 'dir') === 'rtl'; @@ -1344,7 +1255,7 @@ export default function SCEditor(original, userOptions) { * @return {this} */ base.maximize = function (maximize) { - var maximizeSize = 'sceditor-maximize'; + const maximizeSize = 'sceditor-maximize'; if (utils.isUndefined(maximize)) { return dom.hasClass(editorContainer, maximizeSize); @@ -1353,7 +1264,7 @@ export default function SCEditor(original, userOptions) { maximize = !!maximize; if (maximize) { - maximizeScrollPosition = globalWin.pageYOffset; + maximizeScrollPosition = globalWin.scrollY; } dom.toggleClass(globalDoc.documentElement, maximizeSize, maximize); @@ -1399,8 +1310,8 @@ export default function SCEditor(original, userOptions) { autoExpandThrottle = false; if (!autoExpandBounds) { - var height = options.resizeMinHeight || options.height || - dom.height(original); + const height = options.resizeMinHeight || options.height || + dom.height(original); autoExpandBounds = { min: height, @@ -1408,12 +1319,12 @@ export default function SCEditor(original, userOptions) { }; } - var range = globalDoc.createRange(); + const range = globalDoc.createRange(); range.selectNodeContents(wysiwygBody); - var rect = range.getBoundingClientRect(); - var current = wysiwygDocument.documentElement.clientHeight - 1; - var spaceNeeded = rect.bottom - rect.top; + const rect = range.getBoundingClientRect(); + const current = wysiwygDocument.documentElement.clientHeight - 1; + const spaceNeeded = rect.bottom - rect.top; var newHeight = base.height() + 1 + (spaceNeeded - current); if (!ignoreMaxHeight && autoExpandBounds.max !== -1) { @@ -1450,7 +1361,7 @@ export default function SCEditor(original, userOptions) { dom.off(globalDoc, 'click', handleDocumentClick); - var form = original.form; + const form = original.form; if (form) { dom.off(form, 'reset', handleFormReset); dom.off(form, 'submit', base.updateOriginal, dom.EVENT_CAPTURE); @@ -1482,8 +1393,8 @@ export default function SCEditor(original, userOptions) { */ base.createDropDown = function (menuItem, name, content) { // first click for create second click for close - var dropDownCss, - dropDownClass = 'sceditor-' + name; + var dropDownCss; + const dropDownClass = 'sceditor-' + name; base.closeDropDown(); @@ -1494,12 +1405,13 @@ export default function SCEditor(original, userOptions) { dropDownCss = utils.extend({ top: menuItem.offsetTop, - left: menuItem.offsetLeft, + left: menuItem.parentElement.offsetLeft + menuItem.offsetLeft, marginTop: menuItem.clientHeight - }, options.dropDownCss); + }, + options.dropDownCss); dropdown = dom.createElement('div', { - className: 'sceditor-dropdown ' + dropDownClass + className: 'dropdown-menu show sceditor-dropdown ' + dropDownClass }); dom.css(dropdown, dropDownCss); @@ -1511,7 +1423,7 @@ export default function SCEditor(original, userOptions) { }); if (dropdown) { - var first = dom.find(dropdown, 'input,textarea')[0]; + const first = dom.find(dropdown, 'input,textarea')[0]; if (first) { first.focus(); } @@ -1541,17 +1453,17 @@ export default function SCEditor(original, userOptions) { * @private */ handleCutCopyEvt = function (e) { - var range = rangeHelper.selectedRange(); + const range = rangeHelper.selectedRange(); if (range) { - var container = dom.createElement('div', {}, wysiwygDocument); - var firstParent; + const container = dom.createElement('div', {}, wysiwygDocument); + let firstParent; // Copy all inline parent nodes up to the first block parent so can // copy inline styles - var parent = range.commonAncestorContainer; + let parent = range.commonAncestorContainer; while (parent && dom.isInline(parent, true)) { if (parent.nodeType === dom.ELEMENT_NODE) { - var clone = parent.cloneNode(); + const clone = parent.cloneNode(); if (container.firstChild) { dom.appendChild(clone, container.firstChild); } @@ -1601,9 +1513,9 @@ export default function SCEditor(original, userOptions) { */ handlePasteEvt = function (e) { var editable = wysiwygBody; - var clipboard = e.clipboardData; - var loadImage = function (file) { - var reader = new FileReader(); + const clipboard = e.clipboardData; + const loadImage = function (file) { + const reader = new FileReader(); reader.onload = function (e) { handlePasteData({ html: '' @@ -1616,13 +1528,13 @@ export default function SCEditor(original, userOptions) { // old android web views and UC browser which doesn't support the // paste event at all. if (clipboard) { - var data = {}; - var types = clipboard.types; - var items = clipboard.items; + const data = {}; + const types = clipboard.types; + const items = clipboard.items; e.preventDefault(); - for (var i = 0; i < types.length; i++) { + for (let i = 0; i < types.length; i++) { // Word sometimes adds copied text as an image so if HTML // exists prefer that over images if (types.indexOf('text/html') < 0) { @@ -1655,7 +1567,7 @@ export default function SCEditor(original, userOptions) { } setTimeout(function () { - var html = editable.innerHTML; + const html = editable.innerHTML; editable.innerHTML = ''; dom.appendChild(editable, pasteContentFragment); @@ -1675,7 +1587,7 @@ export default function SCEditor(original, userOptions) { * @private */ handlePasteData = function (data) { - var pasteArea = dom.createElement('div', {}, wysiwygDocument); + const pasteArea = dom.createElement('div', {}, wysiwygDocument); pluginManager.call('pasteRaw', data); dom.trigger(editorContainer, 'pasteraw', data); @@ -1690,7 +1602,7 @@ export default function SCEditor(original, userOptions) { pasteArea.innerHTML = escape.entities(data.text || ''); } - var paste = { + const paste = { val: pasteArea.innerHTML }; @@ -1709,7 +1621,7 @@ export default function SCEditor(original, userOptions) { pluginManager.call('pasteHtml', paste); - var parent = rangeHelper.getFirstBlockParent(); + const parent = rangeHelper.getFirstBlockParent(); base.wysiwygEditorInsertHtml(paste.val, null, true); dom.merge(parent); }; @@ -1755,8 +1667,8 @@ export default function SCEditor(original, userOptions) { base.wysiwygEditorInsertHtml = function ( html, endHtml, overrideCodeBlocking ) { - var marker, scrollTop, scrollTo, - editorHeight = dom.height(wysiwygEditor); + var marker, scrollTop, scrollTo; + const editorHeight = dom.height(wysiwygEditor); base.focus(); @@ -1772,7 +1684,6 @@ export default function SCEditor(original, userOptions) { // without affecting the cursor position rangeHelper.insertHTML(html, endHtml); rangeHelper.saveRange(); - replaceEmoticons(); // Fix any invalid nesting, e.g. if a quote or other block is inserted // into a paragraph @@ -1867,9 +1778,9 @@ export default function SCEditor(original, userOptions) { * @memberOf SCEditor.prototype */ base.sourceEditorInsertText = function (text, endText) { - var scrollTop, currentValue, - startPos = sourceEditor.selectionStart, - endPos = sourceEditor.selectionEnd; + var scrollTop, currentValue; + const startPos = sourceEditor.selectionStart; + const endPos = sourceEditor.selectionEnd; scrollTop = sourceEditor.scrollTop; sourceEditor.focus(); @@ -2039,7 +1950,7 @@ export default function SCEditor(original, userOptions) { // Add the selection between start and end if (end) { - var html = rangeHelper.selectedHtml(); + let html = rangeHelper.selectedHtml(); if (filter !== false && 'fragmentToSource' in format) { html = format @@ -2082,10 +1993,10 @@ export default function SCEditor(original, userOptions) { var html; // Create a tmp node to store contents so it can be modified // without affecting anything else. - var tmp = dom.createElement('div', {}, wysiwygDocument); - var childNodes = wysiwygBody.childNodes; + const tmp = dom.createElement('div', {}, wysiwygDocument); + const childNodes = wysiwygBody.childNodes; - for (var i = 0; i < childNodes.length; i++) { + for (let i = 0; i < childNodes.length; i++) { dom.appendChild(tmp, childNodes[i].cloneNode(true)); } @@ -2154,6 +2065,10 @@ export default function SCEditor(original, userOptions) { return val; }; + base.getSourceEditor = function () { + return sourceEditor; + }; + /** * Sets the WYSIWYG HTML editor value. Should only be the HTML * contained within the body tags @@ -2169,7 +2084,6 @@ export default function SCEditor(original, userOptions) { } wysiwygBody.innerHTML = sanitize(value); - replaceEmoticons(); appendNewLine(); triggerValueChanged(); @@ -2203,18 +2117,6 @@ export default function SCEditor(original, userOptions) { original.value = base.val(); }; - /** - * Replaces any emoticon codes in the passed HTML - * with their emoticon images - * @private - */ - replaceEmoticons = function () { - if (options.emoticonsEnabled) { - emoticons - .replace(wysiwygBody, allEmoticons, options.emoticonsCompat); - } - }; - /** * If the editor is in source code mode * @@ -2245,7 +2147,7 @@ export default function SCEditor(original, userOptions) { * @memberOf SCEditor.prototype */ base.sourceMode = function (enable) { - var inSourceMode = base.inSourceMode(); + const inSourceMode = base.inSourceMode(); if (typeof enable !== 'boolean') { return inSourceMode; @@ -2267,7 +2169,7 @@ export default function SCEditor(original, userOptions) { * @memberOf SCEditor.prototype */ base.toggleSourceMode = function () { - var isInSourceMode = base.inSourceMode(); + const isInSourceMode = base.inSourceMode(); // don't allow switching to WYSIWYG if doesn't support it if (!browser.isWysiwygSupported && isInSourceMode) { @@ -2296,6 +2198,10 @@ export default function SCEditor(original, userOptions) { updateToolBar(); updateActiveButtons(); + + if (base.opts.onToggleMode !== undefined) { + base.opts.onToggleMode(base); + } }; /** @@ -2349,8 +2255,8 @@ export default function SCEditor(original, userOptions) { * @memberOf SCEditor.prototype */ base.execCommand = function (command, param) { - var executed = false, - commandObj = base.commands[command]; + var executed = false; + const commandObj = base.commands[command]; base.focus(); @@ -2396,8 +2302,8 @@ export default function SCEditor(original, userOptions) { // If the selection is in an inline wrap it in a block. // Fixes #331 if (currentSelection && currentSelection.collapsed) { - var parent = currentSelection.startContainer; - var offset = currentSelection.startOffset; + let parent = currentSelection.startContainer; + const offset = currentSelection.startOffset; // Handle if selection is placed before/after an element if (offset && parent.nodeType !== dom.TEXT_NODE) { @@ -2442,8 +2348,8 @@ export default function SCEditor(original, userOptions) { */ checkNodeChanged = function () { // check if node has changed - var oldNode, - node = rangeHelper.parentNode(); + var oldNode; + const node = rangeHelper.parentNode(); if (currentNode !== node) { oldNode = currentNode; @@ -2455,6 +2361,17 @@ export default function SCEditor(original, userOptions) { newNode: currentNode }); } + + if (backSpaceHandled) { + const spanNode = currentBlockNode.querySelector('span[style]'); + + if (spanNode) { + dom.removeAttr(spanNode, 'style'); + } + + backSpaceHandled = false; + } + }; /** @@ -2495,8 +2412,8 @@ export default function SCEditor(original, userOptions) { updateActiveButtons = function () { var firstBlock, parent; var activeClass = 'active'; - var doc = wysiwygDocument; - var isSource = base.sourceMode(); + const doc = wysiwygDocument; + const isSource = base.sourceMode(); if (base.readOnly()) { utils.each(dom.find(toolbar, activeClass), function (_, menuItem) { @@ -2510,12 +2427,12 @@ export default function SCEditor(original, userOptions) { firstBlock = rangeHelper.getFirstBlockParent(parent); } - for (var j = 0; j < btnStateHandlers.length; j++) { - var state = 0; - var btn = toolbarButtons[btnStateHandlers[j].name]; - var stateFn = btnStateHandlers[j].state; - var isDisabled = (isSource && !btn._sceTxtMode) || - (!isSource && !btn._sceWysiwygMode); + for (let j = 0; j < btnStateHandlers.length; j++) { + let state = 0; + const btn = toolbarButtons[btnStateHandlers[j].name]; + const stateFn = btnStateHandlers[j].state; + const isDisabled = (isSource && !btn._sceTxtMode) || + (!isSource && !btn._sceWysiwygMode); if (utils.isString(stateFn)) { if (!isSource) { @@ -2556,20 +2473,20 @@ export default function SCEditor(original, userOptions) { // 13 = enter key if (e.which === 13) { - var LIST_TAGS = 'li,ul,ol'; + const LIST_TAGS = 'li,ul,ol'; // "Fix" (cludge) for blocklevel elements being duplicated in some // browsers when enter is pressed instead of inserting a newline if (!dom.is(currentBlockNode, LIST_TAGS) && dom.hasStyling(currentBlockNode)) { - var br = dom.createElement('br', {}, wysiwygDocument); + const br = dom.createElement('br', {}, wysiwygDocument); rangeHelper.insertNode(br); // Last
of a block will be collapsed so need to make sure // the
that was inserted isn't the last node of a block. - var parent = br.parentNode; - var lastChild = parent.lastChild; + const parent = br.parentNode; + let lastChild = parent.lastChild; // Sometimes an empty next node is created after the
if (lastChild && lastChild.nodeType === dom.TEXT_NODE && @@ -2612,7 +2529,7 @@ export default function SCEditor(original, userOptions) { // Add line break after if has styling if (!dom.is(node, '.sceditor-nlf') && dom.hasStyling(node)) { - var paragraph = dom.createElement('p', {}, wysiwygDocument); + const paragraph = dom.createElement('p', {}, wysiwygDocument); paragraph.className = 'sceditor-nlf'; paragraph.innerHTML = '
'; dom.appendChild(wysiwygBody, paragraph); @@ -2668,7 +2585,7 @@ export default function SCEditor(original, userOptions) { return args[0].replace(/\{(\d+)\}/g, function (str, p1) { return args[p1 - 0 + 1] !== undef ? args[p1 - 0 + 1] : - '{' + p1 + '}'; + `{${p1}}`; }); }; @@ -2684,7 +2601,7 @@ export default function SCEditor(original, userOptions) { } // convert the event into a custom event to send - var name = (e.target === sourceEditor ? 'scesrc' : 'scewys') + e.type; + const name = (e.target === sourceEditor ? 'scesrc' : 'scewys') + e.type; if (eventHandlers[name]) { eventHandlers[name].forEach(function (fn) { @@ -2736,8 +2653,8 @@ export default function SCEditor(original, userOptions) { var i = events.length; while (i--) { if (utils.isFunction(handler)) { - var wysEvent = 'scewys' + events[i]; - var srcEvent = 'scesrc' + events[i]; + const wysEvent = 'scewys' + events[i]; + const srcEvent = 'scesrc' + events[i]; // Use custom events to allow passing the instance as the // 2nd argument. // Also allows unbinding without unbinding the editors own @@ -2865,8 +2782,7 @@ export default function SCEditor(original, userOptions) { return; } - var container; - var rng = rangeHelper.selectedRange(); + const rng = rangeHelper.selectedRange(); // Fix FF bug where it shows the cursor in the wrong place // if the editor hasn't had focus before. See issue #393 @@ -2878,6 +2794,7 @@ export default function SCEditor(original, userOptions) { // child of the parent. In Firefox this causes a line break // to occur when something is typed. See issue #321 if (rng && rng.endOffset === 1 && rng.collapsed) { + let container; container = rng.endContainer; if (container && container.childNodes.length === 1 && @@ -3013,115 +2930,6 @@ export default function SCEditor(original, userOptions) { .bind('valuechanged', handler, excludeWysiwyg, excludeSource); }; - /** - * Emoticons keypress handler - * @private - */ - emoticonsKeyPress = function (e) { - var replacedEmoticon, - cachePos = 0, - emoticonsCache = base.emoticonsCache, - curChar = String.fromCharCode(e.which); - - // TODO: Make configurable - if (dom.closest(currentBlockNode, 'code')) { - return; - } - - if (!emoticonsCache) { - emoticonsCache = []; - - utils.each(allEmoticons, function (key, html) { - emoticonsCache[cachePos++] = [key, html]; - }); - - emoticonsCache.sort(function (a, b) { - return a[0].length - b[0].length; - }); - - base.emoticonsCache = emoticonsCache; - base.longestEmoticonCode = - emoticonsCache[emoticonsCache.length - 1][0].length; - } - - replacedEmoticon = rangeHelper.replaceKeyword( - base.emoticonsCache, - true, - true, - base.longestEmoticonCode, - options.emoticonsCompat, - curChar - ); - - if (replacedEmoticon) { - if (!options.emoticonsCompat || !/^\s$/.test(curChar)) { - e.preventDefault(); - } - } - }; - - /** - * Makes sure emoticons are surrounded by whitespace - * @private - */ - emoticonsCheckWhitespace = function () { - emoticons.checkWhitespace(currentBlockNode, rangeHelper); - }; - - /** - * Gets if emoticons are currently enabled - * @return {boolean} - * @function - * @name emoticons - * @memberOf SCEditor.prototype - * @since 1.4.2 - */ - /** - * Enables/disables emoticons - * - * @param {boolean} enable - * @return {this} - * @function - * @name emoticons^2 - * @memberOf SCEditor.prototype - * @since 1.4.2 - */ - base.emoticons = function (enable) { - if (!enable && enable !== false) { - return options.emoticonsEnabled; - } - - options.emoticonsEnabled = enable; - - if (enable) { - dom.on(wysiwygBody, 'keypress', emoticonsKeyPress); - - if (!base.sourceMode()) { - rangeHelper.saveRange(); - - replaceEmoticons(); - triggerValueChanged(false); - - rangeHelper.restoreRange(); - } - } else { - var emoticons = - dom.find(wysiwygBody, 'img[data-sceditor-emoticon]'); - - utils.each(emoticons, function (_, img) { - var text = dom.data(img, 'sceditor-emoticon'); - var textNode = wysiwygDocument.createTextNode(text); - img.parentNode.replaceChild(textNode, img); - }); - - dom.off(wysiwygBody, 'keypress', emoticonsKeyPress); - - triggerValueChanged(); - } - - return base; - }; - /** * Gets the current WYSIWYG editors inline CSS * @@ -3169,6 +2977,15 @@ export default function SCEditor(original, userOptions) { * @private */ handleKeyDown = function (e) { + var autoClosingTags = [ + 'b', 'i', 'u', 'h', 'code', 'img', 'quote', 'left', 'center', 'right', + 'indent', 'list', 'color', + 'size', 'albumimg', 'attach', 'youtube', 'vimeo', + 'instagram', 'twitter', 'facebook', 'googlewidget', 'spoiler', 'userlink', 'googlemaps', + 'hide', 'group-hide', 'hide-thanks', 'hide-reply-thanks', 'hide-reply', 'hide-posts', 'dailymotion', + 'audio', 'media' + ]; + var shortcut = [], SHIFT_KEYS = { '`': '~', @@ -3304,6 +3121,31 @@ export default function SCEditor(original, userOptions) { e.stopPropagation(); e.preventDefault(); } + + // Close tag ']' + if (e.key === ']' && base.inSourceMode()) { + var input = sourceEditor; + + const position = input.selectionStart; + const before = input.value.slice(0, position); + const after = input.value.slice(input.selectionEnd, input.value.length); + let tagName; + + try { + tagName = before.match(/\[([^\]]+)$/)[1].match(/^([a-z1-6]+)/)[1]; + } catch (e) { + // ignore + } + + if (autoClosingTags.indexOf(tagName) > -1) { + const closeTag = `[/${tagName}]`; + + input.value = before + closeTag + after; + input.selectionStart = + input.selectionEnd = position; + input.focus(); + } + } }; /** @@ -3346,7 +3188,9 @@ export default function SCEditor(original, userOptions) { * @private */ handleBackSpace = function (e) { - var node, offset, range, parent; + var node, offset, range, parent; + + backSpaceHandled = true; // 8 is the backspace key if (options.disableBlockRemove || e.which !== 8 || @@ -3394,6 +3238,7 @@ export default function SCEditor(original, userOptions) { while (!dom.hasStyling(block) || dom.isInline(block, true)) { if (!(block = block.parentNode) || dom.is(block, 'body')) { return; + } } @@ -3448,9 +3293,9 @@ export default function SCEditor(original, userOptions) { return; } - var currentHtml, - sourceMode = base.sourceMode(), - hasSelection = !sourceMode && rangeHelper.hasSelection(); + var currentHtml; + const sourceMode = base.sourceMode(); + const hasSelection = !sourceMode && rangeHelper.hasSelection(); // Composition end isn't guaranteed to fire but must have // ended when triggerValueChanged() is called so reset it @@ -3503,10 +3348,10 @@ export default function SCEditor(original, userOptions) { * @private */ valueChangedKeyUp = function (e) { - var which = e.which, - lastChar = valueChangedKeyUp.lastChar, - lastWasSpace = (lastChar === 13 || lastChar === 32), - lastWasDelete = (lastChar === 8 || lastChar === 46); + const which = e.which; + const lastChar = valueChangedKeyUp.lastChar; + const lastWasSpace = (lastChar === 13 || lastChar === 32); + const lastWasDelete = (lastChar === 8 || lastChar === 46); valueChangedKeyUp.lastChar = which; @@ -3559,7 +3404,7 @@ export default function SCEditor(original, userOptions) { }; // run the initializer - loadScripts(); + init(); }; diff --git a/src/lib/browser.js b/src/lib/browser.js index e59904a7d..a433ae4f8 100644 --- a/src/lib/browser.js +++ b/src/lib/browser.js @@ -19,14 +19,14 @@ export var ios = /iPhone|iPod|iPad| wosbrowser\//i.test(USER_AGENT); * @name isWysiwygSupported * @return {boolean} */ -export var isWysiwygSupported = (function () { - var match, isUnsupported; +export var isWysiwygSupported = (function() { + var match, isUnsupported; // IE is the only browser to support documentMode - var ie = !!window.document.documentMode; - var legacyEdge = '-ms-ime-align' in document.documentElement.style; + const ie = !!window.document.documentMode; + const legacyEdge = '-ms-ime-align' in document.documentElement.style; - var div = document.createElement('div'); + const div = document.createElement('div'); div.contentEditable = true; // Check if the contentEditable attribute is supported diff --git a/src/lib/defaultCommands.js b/src/lib/defaultCommands.js index 1a9a4b9c6..08ecc1dd1 100644 --- a/src/lib/defaultCommands.js +++ b/src/lib/defaultCommands.js @@ -1,5 +1,4 @@ import * as dom from './dom.js'; -import * as utils from './utils.js'; import * as escape from './escape.js'; import _tmpl from './templates.js'; @@ -11,8 +10,8 @@ import _tmpl from './templates.js'; function fixFirefoxListBug(editor) { // Only apply to Firefox as will break other browsers. if ('mozHidden' in document) { - var node = editor.getBody(); - var next; + let node = editor.getBody(); + let next; while (node) { next = node; @@ -50,6 +49,57 @@ function fixFirefoxListBug(editor) { * @memberOf jQuery.sceditor */ var defaultCmds = { + + // START_COMMAND: albums + albums: { + exec: function(caller) { + const content = dom.createElement('div'); + const editor = this; + + dom.appendChild(content, + _tmpl('albums', + { + root: editor.opts.root + }, + true)); + + editor.createDropDown(caller, 'albums', content); + + const pageSize = 5; + const pageNumber = 0; + + // eslint-disable-next-line no-undef + getAlbumImagesData(pageSize, pageNumber, false); + }, + tooltip: 'User Albums' + }, + // END_COMMAND + + // START_COMMAND: Attachments + attachments: { + exec: function(caller) { + const content = dom.createElement('div'); + const editor = this; + + dom.appendChild(content, + _tmpl('attachments', + { + root: editor.opts.root + }, + true)); + + editor.createDropDown(caller, 'attachments', content); + + const pageSize = 5; + const pageNumber = 0; + + // eslint-disable-next-line no-undef + getPaginationData(pageSize, pageNumber, false); + }, + tooltip: 'User Attachments' + }, + // END_COMMAND + // START_COMMAND: Bold bold: { exec: 'bold', @@ -77,29 +127,29 @@ var defaultCmds = { tooltip: 'Strikethrough' }, // END_COMMAND - // START_COMMAND: Subscript - subscript: { - exec: 'subscript', - tooltip: 'Subscript' - }, - // END_COMMAND - // START_COMMAND: Superscript - superscript: { - exec: 'superscript', - tooltip: 'Superscript' + // START_COMMAND: Mark + mark: { + exec: function() { + this.wysiwygEditorInsertHtml( + '', + '' + ); + }, + tooltip: 'Highlight', + shortcut: 'Ctrl+H' }, // END_COMMAND // START_COMMAND: Left left: { - state: function (node) { + state: function(node) { if (node && node.nodeType === 3) { node = node.parentNode; } if (node) { - var isLtr = dom.css(node, 'direction') === 'ltr'; - var align = dom.css(node, 'textAlign'); + const isLtr = dom.css(node, 'direction') === 'ltr'; + const align = dom.css(node, 'textAlign'); // Can be -moz-left return /left/.test(align) || @@ -118,14 +168,14 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Right right: { - state: function (node) { + state: function(node) { if (node && node.nodeType === 3) { node = node.parentNode; } if (node) { - var isLtr = dom.css(node, 'direction') === 'ltr'; - var align = dom.css(node, 'textAlign'); + const isLtr = dom.css(node, 'direction') === 'ltr'; + const align = dom.css(node, 'textAlign'); // Can be -moz-right return /right/.test(align) || @@ -145,78 +195,93 @@ var defaultCmds = { // START_COMMAND: Font font: { - _dropDown: function (editor, caller, callback) { - var content = dom.createElement('div'); + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); - dom.on(content, 'click', 'a', function (e) { - callback(dom.data(this, 'font')); - editor.closeDropDown(true); - e.preventDefault(); - }); + dom.on(content, + 'click', + 'a', + function(e) { + callback(dom.data(this, 'font')); + editor.closeDropDown(true); + e.preventDefault(); + }); - editor.opts.fonts.split(',').forEach(function (font) { - dom.appendChild(content, _tmpl('fontOpt', { - font: font - }, true)); + editor.opts.fonts.split(',').forEach(function(font) { + dom.appendChild(content, + _tmpl('fontOpt', + { + font: font + }, + true)); }); editor.createDropDown(caller, 'font-picker', content); }, - exec: function (caller) { + exec: function(caller) { var editor = this; - defaultCmds.font._dropDown(editor, caller, function (fontName) { - editor.execCommand('fontname', fontName); - }); + defaultCmds.font._dropDown(editor, + caller, + function(fontName) { + editor.execCommand('fontname', fontName); + }); }, tooltip: 'Font Name' }, // END_COMMAND // START_COMMAND: Size size: { - _dropDown: function (editor, caller, callback) { - var content = dom.createElement('div'); - - dom.on(content, 'click', 'a', function (e) { - callback(dom.data(this, 'size')); - editor.closeDropDown(true); - e.preventDefault(); - }); + _dropDown: function(editor, caller, callback) { + const content = dom.createElement('div'); + + dom.on(content, + 'click', + 'a', + function(e) { + callback(dom.data(this, 'size')); + editor.closeDropDown(true); + e.preventDefault(); + }); - for (var i = 1; i <= 7; i++) { - dom.appendChild(content, _tmpl('sizeOpt', { - size: i - }, true)); + for (let i = 1; i <= 7; i++) { + dom.appendChild(content, + _tmpl('sizeOpt', + { + size: i + }, + true)); } editor.createDropDown(caller, 'fontsize-picker', content); }, - exec: function (caller) { + exec: function(caller) { var editor = this; - defaultCmds.size._dropDown(editor, caller, function (fontSize) { - editor.execCommand('fontsize', fontSize); - }); + defaultCmds.size._dropDown(editor, + caller, + function(fontSize) { + editor.execCommand('fontsize', fontSize); + }); }, tooltip: 'Font Size' }, // END_COMMAND // START_COMMAND: Colour color: { - _dropDown: function (editor, caller, callback) { - var content = dom.createElement('div'), - html = '', - cmd = defaultCmds.color; + _dropDown: function(editor, caller, callback) { + const content = dom.createElement('div'); + var html = ''; + const cmd = defaultCmds.color; if (!cmd._htmlCache) { - editor.opts.colors.split('|').forEach(function (column) { + editor.opts.colors.split('|').forEach(function(column) { html += '
'; - column.split(',').forEach(function (color) { + column.split(',').forEach(function(color) { html += - ''; + ``; }); html += '
'; @@ -227,20 +292,25 @@ var defaultCmds = { dom.appendChild(content, dom.parseHTML(cmd._htmlCache)); - dom.on(content, 'click', 'a', function (e) { - callback(dom.data(this, 'color')); - editor.closeDropDown(true); - e.preventDefault(); - }); + dom.on(content, + 'click', + 'a', + function(e) { + callback(dom.data(this, 'color')); + editor.closeDropDown(true); + e.preventDefault(); + }); editor.createDropDown(caller, 'color-picker', content); }, - exec: function (caller) { + exec: function(caller) { var editor = this; - defaultCmds.color._dropDown(editor, caller, function (color) { - editor.execCommand('forecolor', color); - }); + defaultCmds.color._dropDown(editor, + caller, + function(color) { + editor.execCommand('forecolor', color); + }); }, tooltip: 'Font Color' }, @@ -278,28 +348,34 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Paste Text pastetext: { - exec: function (caller) { - var val, + exec: function(caller) { + var val, content = dom.createElement('div'), - editor = this; - - dom.appendChild(content, _tmpl('pastetext', { - label: editor._( - 'Paste your text inside the following box:' - ), - insert: editor._('Insert') - }, true)); - - dom.on(content, 'click', '.button', function (e) { - val = dom.find(content, '#txt')[0].value; - - if (val) { - editor.wysiwygEditorInsertText(val); - } + editor = this; + + dom.appendChild(content, + _tmpl('pastetext', + { + label: editor._( + 'Paste your text inside the following box:' + ), + insert: editor._('Insert') + }, + true)); + + dom.on(content, + 'click', + '.button', + function(e) { + val = dom.find(content, '#txt')[0].value; + + if (val) { + editor.wysiwygEditorInsertText(val); + } - editor.closeDropDown(true); - e.preventDefault(); - }); + editor.closeDropDown(true); + e.preventDefault(); + }); editor.createDropDown(caller, 'pastetext', content); }, @@ -308,7 +384,7 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Bullet List bulletlist: { - exec: function () { + exec: function() { fixFirefoxListBug(this); this.execCommand('insertunorderedlist'); }, @@ -317,7 +393,7 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Ordered List orderedlist: { - exec: function () { + exec: function() { fixFirefoxListBug(this); this.execCommand('insertorderedlist'); }, @@ -326,9 +402,9 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Indent indent: { - state: function (parent, firstBlock) { + state: function(parent, firstBlock) { // Only works with lists, for now - var range, startParent, endParent; + var range, startParent, endParent; if (dom.is(firstBlock, 'li')) { return 0; @@ -341,7 +417,7 @@ var defaultCmds = { range = this.getRangeHelper().selectedRange(); startParent = range.startContainer.parentNode; - endParent = range.endContainer.parentNode; + endParent = range.endContainer.parentNode; // TODO: could use nodeType for this? // Maybe just check the firstBlock contains both the start @@ -352,7 +428,8 @@ var defaultCmds = { if (startParent !== startParent.parentNode.firstElementChild || // work around a bug in FF - (dom.is(endParent, 'li') && endParent !== + (dom.is(endParent, 'li') && + endParent !== endParent.parentNode.lastElementChild)) { return 0; } @@ -360,9 +437,9 @@ var defaultCmds = { return -1; }, - exec: function () { - var editor = this, - block = editor.getRangeHelper().getFirstBlockParent(); + exec: function() { + const editor = this; + const block = editor.getRangeHelper().getFirstBlockParent(); editor.focus(); @@ -379,11 +456,11 @@ var defaultCmds = { // END_COMMAND // START_COMMAND: Outdent outdent: { - state: function (parents, firstBlock) { + state: function(parents, firstBlock) { return dom.closest(firstBlock, 'ul,ol,menu') ? 0 : -1; }, - exec: function () { - var block = this.getRangeHelper().getFirstBlockParent(); + exec: function() { + const block = this.getRangeHelper().getFirstBlockParent(); if (dom.closest(block, 'ul,ol,menu')) { this.execCommand('outdent'); } @@ -394,37 +471,43 @@ var defaultCmds = { // START_COMMAND: Table table: { - exec: function (caller) { - var editor = this, + exec: function(caller) { + var editor = this, content = dom.createElement('div'); - dom.appendChild(content, _tmpl('table', { - rows: editor._('Rows:'), - cols: editor._('Cols:'), - insert: editor._('Insert') - }, true)); - - dom.on(content, 'click', '.button', function (e) { - var rows = Number(dom.find(content, '#rows')[0].value), - cols = Number(dom.find(content, '#cols')[0].value), - html = ''; - - if (rows > 0 && cols > 0) { - html += Array(rows + 1).join( - '' + + dom.appendChild(content, + _tmpl('table', + { + rows: editor._('Rows:'), + cols: editor._('Cols:'), + insert: editor._('Insert') + }, + true)); + + dom.on(content, + 'click', + '.button', + function(e) { + var rows = Number(dom.find(content, '#rows')[0].value), + cols = Number(dom.find(content, '#cols')[0].value), + html = '
'; + + if (rows > 0 && cols > 0) { + html += Array(rows + 1).join( + '' + Array(cols + 1).join( - '' + '' ) + - '' - ); + '' + ); - html += '


'; + html += ''; - editor.wysiwygEditorInsertHtml(html); - editor.closeDropDown(true); - e.preventDefault(); - } - }); + editor.wysiwygEditorInsertHtml(html); + editor.closeDropDown(true); + e.preventDefault(); + } + }); editor.createDropDown(caller, 'inserttable', content); }, @@ -432,79 +515,158 @@ var defaultCmds = { }, // END_COMMAND - // START_COMMAND: Horizontal Rule - horizontalrule: { - exec: 'inserthorizontalrule', - tooltip: 'Insert a horizontal rule' + // START_COMMAND: Code + code: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); + + dom.on(content, + 'click', + 'a', + function(e) { + callback(dom.data(this, 'language')); + editor.closeDropDown(true); + e.preventDefault(); + }); + + editor.opts.codeLanguages.forEach(function(language) { + dom.appendChild(content, + _tmpl('codeOpt', + { + language: language.Value, + languageName: language.Text + }, + true)); + }); + + editor.createDropDown(caller, 'codeLanguage-picker', content); + }, + exec: function(caller) { + var editor = this; + + defaultCmds.code._dropDown(editor, + caller, + function(codeLanguageName) { + + editor.wysiwygEditorInsertHtml( + `
`,
+						'
' + ); + }); + }, + tooltip: 'Code' }, // END_COMMAND + // START_COMMAND: Code - code: { - exec: function () { - this.wysiwygEditorInsertHtml( - '', - '
' - ); + extensions: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); + + dom.on(content, + 'click', + 'a', + function(e) { + callback(dom.data(this, 'language')); + editor.closeDropDown(true); + e.preventDefault(); + }); + + fetch(editor.opts.extensionsUrl, + { + method: 'GET' + }).then(res => res.json()).then(data => { + data.forEach(function(extension) { + if (!extension.useToolbar) { + dom.appendChild(content, + _tmpl('extensionOpt', + { + extension: extension.name + }, + true)); + } + }); + }); + + editor.createDropDown(caller, 'extensions-picker', content); }, - tooltip: 'Code' + exec: function(caller) { + var editor = this; + + defaultCmds.extensions._dropDown(editor, + caller, + function(extension) { + + editor.wysiwygEditorInsertText( + `[${extension}]`, + `[/${extension}]` + ); + }); + + + }, + tooltip: 'More BBCode' }, // END_COMMAND // START_COMMAND: Image image: { - _dropDown: function (editor, caller, selected, cb) { - var content = dom.createElement('div'); - - dom.appendChild(content, _tmpl('image', { - url: editor._('URL:'), - width: editor._('Width (optional):'), - height: editor._('Height (optional):'), - insert: editor._('Insert') - }, true)); + _dropDown: function(editor, caller, cb) { + var content = dom.createElement('div'); + dom.appendChild(content, + _tmpl('image', + { + url: editor._('URL:'), + desc: editor._('Description (optional):'), + insert: editor._('Insert') + }, + true)); - var urlInput = dom.find(content, '#image')[0]; - urlInput.value = selected; + var linkInput = dom.find(content, '#link')[0]; - dom.on(content, 'click', '.button', function (e) { - if (urlInput.value) { - cb( - urlInput.value, - dom.find(content, '#width')[0].value, - dom.find(content, '#height')[0].value - ); + function insertUrl(e) { + const desc = dom.find(content, '#des')[0].value; + if (linkInput.value) { + cb(linkInput.value, desc); } editor.closeDropDown(true); e.preventDefault(); - }); + } + + dom.on(content, 'click', '.button', insertUrl); + dom.on(content, + 'keypress', + function(e) { + // 13 = enter key + if (e.which === 13 && linkInput.value) { + insertUrl(e); + } + }, + dom.EVENT_CAPTURE); editor.createDropDown(caller, 'insertimage', content); }, - exec: function (caller) { - var editor = this; + exec: function(caller) { + var editor = this; defaultCmds.image._dropDown( editor, caller, - '', - function (url, width, height) { - var attrs = ''; - - if (width) { - attrs += ' width="' + parseInt(width, 10) + '"'; - } + function(url, text) { + var attrs = ''; - if (height) { - attrs += ' height="' + parseInt(height, 10) + '"'; + if (text) { + attrs += ` alt="${escape.entities(text)}"`; } - attrs += ' src="' + escape.entities(url) + '"'; + attrs += ` src="${escape.entities(url)}"`; editor.wysiwygEditorInsertHtml( - '' + `` ); } ); @@ -515,44 +677,47 @@ var defaultCmds = { // START_COMMAND: E-mail email: { - _dropDown: function (editor, caller, cb) { - var content = dom.createElement('div'); - - dom.appendChild(content, _tmpl('email', { - label: editor._('E-mail:'), - desc: editor._('Description (optional):'), - insert: editor._('Insert') - }, true)); - - dom.on(content, 'click', '.button', function (e) { - var email = dom.find(content, '#email')[0].value; + _dropDown: function(editor, caller, cb) { + var content = dom.createElement('div'); - if (email) { - cb(email, dom.find(content, '#des')[0].value); - } + dom.appendChild(content, + _tmpl('email', + { + label: editor._('E-mail:'), + desc: editor._('Description (optional):'), + insert: editor._('Insert') + }, + true)); + + dom.on(content, + 'click', + '.button', + function(e) { + const email = dom.find(content, '#email')[0].value; + + if (email) { + cb(email, dom.find(content, '#des')[0].value); + } - editor.closeDropDown(true); - e.preventDefault(); - }); + editor.closeDropDown(true); + e.preventDefault(); + }); editor.createDropDown(caller, 'insertemail', content); }, - exec: function (caller) { - var editor = this; + exec: function(caller) { + var editor = this; defaultCmds.email._dropDown( editor, caller, - function (email, text) { + function(email, text) { if (!editor.getRangeHelper().selectedHtml() || text) { editor.wysiwygEditorInsertHtml( - '' + - escape.entities((text || email)) + - '' + `${escape.entities((text || email))}` ); } else { - editor.execCommand('createlink', 'mailto:' + email); + editor.execCommand('createlink', `mailto:${email}`); } } ); @@ -563,14 +728,17 @@ var defaultCmds = { // START_COMMAND: Link link: { - _dropDown: function (editor, caller, cb) { + _dropDown: function(editor, caller, cb) { var content = dom.createElement('div'); - dom.appendChild(content, _tmpl('link', { - url: editor._('URL:'), - desc: editor._('Description (optional):'), - ins: editor._('Insert') - }, true)); + dom.appendChild(content, + _tmpl('link', + { + url: editor._('URL:'), + desc: editor._('Description (optional):'), + ins: editor._('Insert') + }, + true)); var linkInput = dom.find(content, '#link')[0]; @@ -584,29 +752,32 @@ var defaultCmds = { } dom.on(content, 'click', '.button', insertUrl); - dom.on(content, 'keypress', function (e) { - // 13 = enter key - if (e.which === 13 && linkInput.value) { - insertUrl(e); - } - }, dom.EVENT_CAPTURE); + dom.on(content, + 'keypress', + function(e) { + // 13 = enter key + if (e.which === 13 && linkInput.value) { + insertUrl(e); + } + }, + dom.EVENT_CAPTURE); editor.createDropDown(caller, 'insertlink', content); }, - exec: function (caller) { + exec: function(caller) { var editor = this; - defaultCmds.link._dropDown(editor, caller, function (url, text) { - if (text || !editor.getRangeHelper().selectedHtml()) { - editor.wysiwygEditorInsertHtml( - '' + - escape.entities(text || url) + - '' - ); - } else { - editor.execCommand('createlink', url); - } - }); + defaultCmds.link._dropDown(editor, + caller, + function(url, text) { + if (text || !editor.getRangeHelper().selectedHtml()) { + editor.wysiwygEditorInsertHtml( + `${escape.entities(text || url)}` + ); + } else { + editor.execCommand('createlink', url); + } + }); }, tooltip: 'Insert a link' }, @@ -614,11 +785,11 @@ var defaultCmds = { // START_COMMAND: Unlink unlink: { - state: function () { + state: function() { return dom.closest(this.currentNode(), 'a') ? 0 : -1; }, - exec: function () { - var anchor = dom.closest(this.currentNode(), 'a'); + exec: function() { + const anchor = dom.closest(this.currentNode(), 'a'); if (anchor) { while (anchor.firstChild) { @@ -635,21 +806,23 @@ var defaultCmds = { // START_COMMAND: Quote quote: { - exec: function (caller, html, author) { - var before = '
', - end = '
'; + exec: function(caller, html, author) { + var before = + '
'; + var end = '
'; // if there is HTML passed set end to null so any selected // text is replaced if (html) { - author = (author ? '' + - escape.entities(author) + - '' : ''); - before = before + author + html + end; - end = null; - // if not add a newline to the end of the inserted quote + author = (author + ? `${ + escape.entities(author)}` + : ''); + before = before + html + author + end; + end = null; + // if not add a newline to the end of the inserted quote } else if (this.getRangeHelper().selectedHtml() === '') { - end = '
' + end; + // end = `
${end}`; } this.wysiwygEditorInsertHtml(before, end); @@ -658,128 +831,237 @@ var defaultCmds = { }, // END_COMMAND - // START_COMMAND: Emoticons - emoticon: { - exec: function (caller) { + // START_COMMAND: media + media: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); + + dom.appendChild(content, + _tmpl('mediaMenu', + { + label: editor._('Media URL:'), + insert: editor._('Insert') + }, + true)); + + dom.on(content, + 'click', + '.button', + function(e) { + const url = dom.find(content, '#link')[0].value; + + if (!url.startsWith('http')) { + alert('Not a valid URL!'); + return; + } + + callback(url); + + editor.closeDropDown(true); + e.preventDefault(); + }); + + editor.createDropDown(caller, 'insertmedia', content); + }, + exec: function(btn) { var editor = this; - var createContent = function (includeMore) { - var moreLink, - opts = editor.opts, - emoticonsRoot = opts.emoticonsRoot || '', - emoticonsCompat = opts.emoticonsCompat, - rangeHelper = editor.getRangeHelper(), - startSpace = emoticonsCompat && - rangeHelper.getOuterText(true, 1) !== ' ' ? ' ' : '', - endSpace = emoticonsCompat && - rangeHelper.getOuterText(false, 1) !== ' ' ? ' ' : '', - content = dom.createElement('div'), - line = dom.createElement('div'), - perLine = 0, - emoticons = utils.extend( - {}, - opts.emoticons.dropdown, - includeMore ? opts.emoticons.more : {} - ); + defaultCmds.media._dropDown(editor, + btn, + function(url) { + editor.wysiwygEditorInsertHtml(`[media]${url}[/media]`); + }); + }, + tooltip: 'Insert an embed media like a YouTube video, facebook post or twitter status.' + }, + // END_COMMAND + + // START_COMMAND: vimeo + vimeo: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); + + dom.appendChild(content, + _tmpl('youtubeMenu', + { + label: editor._('Video URL:'), + insert: editor._('Insert') + }, + true)); - dom.appendChild(content, line); + dom.on(content, + 'click', + '.button', + function(e) { + const url = dom.find(content, '#link')[0].value; - perLine = Math.sqrt(Object.keys(emoticons).length); + if (url !== '') { + const matches = url.match(/vimeo\..*\/(\d+)(?:$|\/)/); - dom.on(content, 'click', 'img', function (e) { - editor.insert(startSpace + dom.attr(this, 'alt') + endSpace, - null, false).closeDropDown(true); + callback(url, matches[1]); + } + editor.closeDropDown(true); e.preventDefault(); }); - utils.each(emoticons, function (code, emoticon) { - dom.appendChild(line, dom.createElement('img', { - src: emoticonsRoot + (emoticon.url || emoticon), - alt: code, - title: emoticon.tooltip || code - })); + editor.createDropDown(caller, 'insertlink', content); + }, + exec: function(btn) { + var editor = this; + + defaultCmds.vimeo._dropDown(editor, + btn, + function(url, id) { + editor.wysiwygEditorInsertHtml(_tmpl('vimeo', + { + url: url, + vimeoId: id + })); + }); + }, + tooltip: 'Insert a Vimeo video' + }, + // END_COMMAND + + // START_COMMAND: instagram + instagram: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); - if (line.children.length >= perLine) { - line = dom.createElement('div'); - dom.appendChild(content, line); + dom.appendChild(content, + _tmpl('instagramMenu', + { + label: editor._('Instagram Post URL:'), + insert: editor._('Insert') + }, + true)); + + dom.on(content, + 'click', + '.button', + function(e) { + const url = dom.find(content, '#link')[0].value; + var id = ''; + + if (url !== '') { + const matches = url.match(/\/(p|tv|reel)\/(.*?)\//); + + if (matches) { + id = matches[2]; + callback(url, id); + } } + + editor.closeDropDown(true); + e.preventDefault(); }); - if (!includeMore && opts.emoticons.more) { - moreLink = dom.createElement('a', { - className: 'sceditor-more' - }); + editor.createDropDown(caller, 'insertlink', content); + }, + exec: function(btn) { + var editor = this; - dom.appendChild(moreLink, - document.createTextNode(editor._('More'))); + defaultCmds.instagram._dropDown(editor, + btn, + function(url, id) { + editor.wysiwygEditorInsertHtml(_tmpl('instagram', + { + url: url, + id: id + })); + }); + }, + tooltip: 'Insert an Instagram Post' + }, + // END_COMMAND - dom.on(moreLink, 'click', function (e) { - editor.createDropDown( - caller, 'more-emoticons', createContent(true) - ); + // START_COMMAND: facebook + facebook: { + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); - e.preventDefault(); - }); + dom.appendChild(content, + _tmpl('facebookMenu', + { + label: editor._('Facebook post URL:'), + insert: editor._('Insert') + }, + true)); - dom.appendChild(content, moreLink); - } + dom.on(content, + 'click', + '.button', + function(e) { + const url = dom.find(content, '#link')[0].value; + + callback(url); - return content; - }; + editor.closeDropDown(true); + e.preventDefault(); + }); - editor.createDropDown(caller, 'emoticons', createContent(false)); + editor.createDropDown(caller, 'insertlink', content); }, - txtExec: function (caller) { - defaultCmds.emoticon.exec.call(this, caller); + exec: function(btn) { + var editor = this; + + defaultCmds.facebook._dropDown(editor, + btn, + function(url) { + editor.wysiwygEditorInsertHtml(_tmpl('facebook', + { + url: url + })); + }); }, - tooltip: 'Insert an emoticon' + tooltip: 'Insert an Facebook Post' }, // END_COMMAND - // START_COMMAND: YouTube + // START_COMMAND: youtube youtube: { - _dropDown: function (editor, caller, callback) { - var content = dom.createElement('div'); - - dom.appendChild(content, _tmpl('youtubeMenu', { - label: editor._('Video URL:'), - insert: editor._('Insert') - }, true)); - - dom.on(content, 'click', '.button', function (e) { - var val = dom.find(content, '#link')[0].value; - var idMatch = val.match(/(?:v=|v\/|embed\/|youtu.be\/)?([a-zA-Z0-9_-]{11})/); - var timeMatch = val.match(/[&|?](?:star)?t=((\d+[hms]?){1,3})/); - var time = 0; - - if (timeMatch) { - utils.each(timeMatch[1].split(/[hms]/), function (i, val) { - if (val !== '') { - time = (time * 60) + Number(val); - } - }); - } + _dropDown: function(editor, caller, callback) { + var content = dom.createElement('div'); - if (idMatch && /^[a-zA-Z0-9_\-]{11}$/.test(idMatch[1])) { - callback(idMatch[1], time); - } + dom.appendChild(content, + _tmpl('youtubeMenu', + { + label: editor._('Video URL:'), + insert: editor._('Insert') + }, + true)); - editor.closeDropDown(true); - e.preventDefault(); - }); + dom.on(content, + 'click', + '.button', + function(e) { + const url = dom.find(content, '#link')[0].value; + const idMatch = url.match(/(?:v=|v\/|embed\/|youtu.be\/)?([a-zA-Z0-9_-]{11})/); + + + if (idMatch && /^[a-zA-Z0-9_\-]{11}$/.test(idMatch[1])) { + callback(url, idMatch[1]); + } + + editor.closeDropDown(true); + e.preventDefault(); + }); editor.createDropDown(caller, 'insertlink', content); }, - exec: function (btn) { + exec: function(btn) { var editor = this; - defaultCmds.youtube._dropDown(editor, btn, function (id, time) { - editor.wysiwygEditorInsertHtml(_tmpl('youtube', { - id: id, - time: time - })); - }); + defaultCmds.youtube._dropDown(editor, + btn, + function(url, id) { + editor.wysiwygEditorInsertHtml(_tmpl('youtube', + { + url: url, + id: id + })); + }); }, tooltip: 'Insert a YouTube video' }, @@ -787,22 +1069,22 @@ var defaultCmds = { // START_COMMAND: Date date: { - _date: function (editor) { - var now = new Date(), - year = now.getYear(), + _date: function(editor) { + const now = new Date(); + var year = now.getYear(), month = now.getMonth() + 1, - day = now.getDate(); + day = now.getDate(); if (year < 2000) { year = 1900 + year; } if (month < 10) { - month = '0' + month; + month = `0${month}`; } if (day < 10) { - day = '0' + day; + day = `0${day}`; } return editor.opts.dateFormat @@ -810,10 +1092,10 @@ var defaultCmds = { .replace(/month/i, month) .replace(/day/i, day); }, - exec: function () { + exec: function() { this.insertText(defaultCmds.date._date(this)); }, - txtExec: function () { + txtExec: function() { this.insertText(defaultCmds.date._date(this)); }, tooltip: 'Insert current date' @@ -822,113 +1104,62 @@ var defaultCmds = { // START_COMMAND: Time time: { - _time: function () { - var now = new Date(), - hours = now.getHours(), - mins = now.getMinutes(), - secs = now.getSeconds(); + _time: function() { + const now = new Date(); + var hours = now.getHours(), + mins = now.getMinutes(), + secs = now.getSeconds(); if (hours < 10) { - hours = '0' + hours; + hours = `0${hours}`; } if (mins < 10) { - mins = '0' + mins; + mins = `0${mins}`; } if (secs < 10) { - secs = '0' + secs; + secs = `0${secs}`; } return hours + ':' + mins + ':' + secs; }, - exec: function () { + exec: function() { this.insertText(defaultCmds.time._time()); }, - txtExec: function () { + txtExec: function() { this.insertText(defaultCmds.time._time()); }, tooltip: 'Insert current time' }, // END_COMMAND - - // START_COMMAND: Ltr - ltr: { - state: function (parents, firstBlock) { - return firstBlock && firstBlock.style.direction === 'ltr'; - }, - exec: function () { - var editor = this, - rangeHelper = editor.getRangeHelper(), - node = rangeHelper.getFirstBlockParent(); - - editor.focus(); - - if (!node || dom.is(node, 'body')) { - editor.execCommand('formatBlock', 'p'); - - node = rangeHelper.getFirstBlockParent(); - - if (!node || dom.is(node, 'body')) { - return; - } - } - - var toggleValue = dom.css(node, 'direction') === 'ltr' ? '' : 'ltr'; - dom.css(node, 'direction', toggleValue); - }, - tooltip: 'Left-to-Right' - }, - // END_COMMAND - - // START_COMMAND: Rtl - rtl: { - state: function (parents, firstBlock) { - return firstBlock && firstBlock.style.direction === 'rtl'; - }, - exec: function () { - var editor = this, - rangeHelper = editor.getRangeHelper(), - node = rangeHelper.getFirstBlockParent(); - - editor.focus(); - - if (!node || dom.is(node, 'body')) { - editor.execCommand('formatBlock', 'p'); - - node = rangeHelper.getFirstBlockParent(); - - if (!node || dom.is(node, 'body')) { - return; - } - } - - var toggleValue = dom.css(node, 'direction') === 'rtl' ? '' : 'rtl'; - dom.css(node, 'direction', toggleValue); - }, - tooltip: 'Right-to-Left' + // START_COMMAND: Undo + undo: { + exec: 'undo', + tooltip: 'Undo', + shortcut: 'Ctrl+Z' }, // END_COMMAND - - // START_COMMAND: Print - print: { - exec: 'print', - tooltip: 'Print' + // START_COMMAND: Redo + redo: { + exec: 'redo', + tooltip: 'Redo', + shortcut: 'Ctrl+Y' }, // END_COMMAND // START_COMMAND: Maximize maximize: { - state: function () { + state: function() { return this.maximize(); }, - exec: function () { + exec: function() { this.maximize(!this.maximize()); this.focus(); }, - txtExec: function () { + txtExec: function() { this.maximize(!this.maximize()); this.focus(); }, @@ -939,14 +1170,14 @@ var defaultCmds = { // START_COMMAND: Source source: { - state: function () { + state: function() { return this.sourceMode(); }, - exec: function () { + exec: function() { this.toggleSourceMode(); this.focus(); }, - txtExec: function () { + txtExec: function() { this.toggleSourceMode(); this.focus(); }, @@ -954,6 +1185,24 @@ var defaultCmds = { shortcut: 'Ctrl+Shift+S' }, // END_COMMAND + // START_COMMAND: Reply + reply: { + exec: function() { + if (document.getElementById('QuickReplyDialog') !== null) { + document.querySelector('[data-bs-save*="modal"]').click(); + } else if (document.querySelector('[formaction*="PostReply"]') !== null) { + document.querySelector('[formaction*="PostReply"]').click(); + } else if (document.querySelector('[id*="QuickReply"]') !== null) { + document.querySelector('[id*="QuickReply"]').click(); + } else if (document.querySelector('[id*="PostReply"]') !== null) { + window.location.href = document.querySelector('[id*="PostReply"]').href; + } + }, + tooltip: 'Post Reply', + shortcut: 'Ctrl+Enter' + }, + // END_COMMAND + // this is here so that commands above can be removed // without having to remove the , after the last one. diff --git a/src/lib/defaultOptions.js b/src/lib/defaultOptions.js index 587cd71b2..b4a676ef5 100644 --- a/src/lib/defaultOptions.js +++ b/src/lib/defaultOptions.js @@ -12,11 +12,13 @@ export default { * * @type {string} */ - toolbar: 'bold,italic,underline,strike,subscript,superscript|' + - 'left,center,right,justify|font,size,color,removeformat|' + - 'cut,copy,pastetext|bulletlist,orderedlist,indent,outdent|' + - 'table|code,quote|horizontalrule,image,email,link,unlink|' + - 'emoticon,youtube,date,time|ltr,rtl|print,maximize,source', + toolbar: 'bold,italic,underline,strike|' + + 'font,size,color|mark|' + + 'email,link,unlink,quote,code|image|' + + 'bulletlist,orderedlist|left,center,right|indent,outdent|' + + 'cut,copy,pastetext,removeformat|' + + 'undo,redo|' + + 'youtube,vimeo,instagram,facebook,media,extensions|source|reply', /** * Comma separated list of commands to excludes from the toolbar @@ -25,13 +27,27 @@ export default { */ toolbarExclude: null, + /** + * Maximum Number of allowed Characters + * + * @type {?number} + */ + maxLength: null, + /** * Stylesheet to include in the WYSIWYG editor. This is what will style * the WYSIWYG elements * - * @type {string} + * @type {Array} */ - style: 'jquery.sceditor.default.css', + styles: [], + + /** + * The bootstrap theme mode. This will be applied to the editor WYSIWYG mode (iframe) + * + * @type {string} + */ + themeMode: attr(document.documentElement, 'data-bs-theme') || 'light', /** * Comma separated list of fonts for the font selector @@ -41,6 +57,44 @@ export default { fonts: 'Arial,Arial Black,Comic Sans MS,Courier New,Georgia,Impact,' + 'Sans-serif,Serif,Times New Roman,Trebuchet MS,Verdana', + /** + * Default format + * + * @type {string} + */ + format: 'bbcode', + + /** + * Default icon set + * + * @type {string} + */ + icons: 'fontawesome', + + /** + * Comma separated list of code languages for the code block selector + * + * @type {Array} + */ + codeLanguages: [ + { Value: 'markup', Text: 'Plain Text' }, + { Value: 'bash', Text: 'Bash(shell)' }, + { Value: 'c', Text: 'C' }, + { Value: 'cpp', Text: 'C++' }, + { Value: 'csharp', Text: 'C#' }, + { Value: 'css', Text: 'CSS' }, + { Value: 'scss', Text: 'SCSS' }, + { Value: 'git', Text: 'Git' }, + { Value: 'markup', Text: 'HTML' }, + { Value: 'java', Text: 'Java' }, + { Value: 'javascript', Text: 'JavaScript' }, + { Value: 'json', Text: 'JSON' }, + { Value: 'python', Text: 'Python' }, + { Value: 'sql', Text: 'SQL' }, + { Value: 'markup', Text: 'XML' }, + { Value: 'vb', Text: 'Visual Basic' } + ], + /** * Colors should be comma separated and have a bar | to signal a new * column. @@ -50,13 +104,13 @@ export default { * @type {string} */ colors: '#000000,#44B8FF,#1E92F7,#0074D9,#005DC2,#00369B,#b3d5f4|' + - '#444444,#C3FFFF,#9DF9FF,#7FDBFF,#68C4E8,#419DC1,#d9f4ff|' + - '#666666,#72FF84,#4CEA5E,#2ECC40,#17B529,#008E02,#c0f0c6|' + - '#888888,#FFFF44,#FFFA1E,#FFDC00,#E8C500,#C19E00,#fff5b3|' + - '#aaaaaa,#FFC95F,#FFA339,#FF851B,#E86E04,#C14700,#ffdbbb|' + - '#cccccc,#FF857A,#FF5F54,#FF4136,#E82A1F,#C10300,#ffc6c3|' + - '#eeeeee,#FF56FF,#FF30DC,#F012BE,#D900A7,#B20080,#fbb8ec|' + - '#ffffff,#F551FF,#CF2BE7,#B10DC9,#9A00B2,#9A00B2,#e8b6ef', + '#444444,#C3FFFF,#9DF9FF,#7FDBFF,#68C4E8,#419DC1,#d9f4ff|' + + '#666666,#72FF84,#4CEA5E,#2ECC40,#17B529,#008E02,#c0f0c6|' + + '#888888,#FFFF44,#FFFA1E,#FFDC00,#E8C500,#C19E00,#fff5b3|' + + '#aaaaaa,#FFC95F,#FFA339,#FF851B,#E86E04,#C14700,#ffdbbb|' + + '#cccccc,#FF857A,#FF5F54,#FF4136,#E82A1F,#C10300,#ffc6c3|' + + '#eeeeee,#FF56FF,#FF30DC,#F012BE,#D900A7,#B20080,#fbb8ec|' + + '#ffffff,#F551FF,#CF2BE7,#B10DC9,#9A00B2,#9A00B2,#e8b6ef', /** * The locale to use. @@ -70,85 +124,12 @@ export default { */ charset: 'utf-8', - /** - * Compatibility mode for emoticons. - * - * Helps if you have emoticons such as :/ which would put an emoticon - * inside http:// - * - * This mode requires emoticons to be surrounded by whitespace or end of - * line chars. This mode has limited As You Type emoticon conversion - * support. It will not replace AYT for end of line chars, only - * emoticons surrounded by whitespace. They will still be replaced - * correctly when loaded just not AYT. - * - * @type {boolean} - */ - emoticonsCompat: false, - - /** - * If to enable emoticons. Can be changes at runtime using the - * emoticons() method. - * - * @type {boolean} - * @since 1.4.2 - */ - emoticonsEnabled: true, - - /** - * Emoticon root URL - * - * @type {string} - */ - emoticonsRoot: '', - emoticons: { - dropdown: { - ':)': 'emoticons/smile.png', - ':angel:': 'emoticons/angel.png', - ':angry:': 'emoticons/angry.png', - '8-)': 'emoticons/cool.png', - ':\'(': 'emoticons/cwy.png', - ':ermm:': 'emoticons/ermm.png', - ':D': 'emoticons/grin.png', - '<3': 'emoticons/heart.png', - ':(': 'emoticons/sad.png', - ':O': 'emoticons/shocked.png', - ':P': 'emoticons/tongue.png', - ';)': 'emoticons/wink.png' - }, - more: { - ':alien:': 'emoticons/alien.png', - ':blink:': 'emoticons/blink.png', - ':blush:': 'emoticons/blush.png', - ':cheerful:': 'emoticons/cheerful.png', - ':devil:': 'emoticons/devil.png', - ':dizzy:': 'emoticons/dizzy.png', - ':getlost:': 'emoticons/getlost.png', - ':happy:': 'emoticons/happy.png', - ':kissing:': 'emoticons/kissing.png', - ':ninja:': 'emoticons/ninja.png', - ':pinch:': 'emoticons/pinch.png', - ':pouty:': 'emoticons/pouty.png', - ':sick:': 'emoticons/sick.png', - ':sideways:': 'emoticons/sideways.png', - ':silly:': 'emoticons/silly.png', - ':sleeping:': 'emoticons/sleeping.png', - ':unsure:': 'emoticons/unsure.png', - ':woot:': 'emoticons/w00t.png', - ':wassat:': 'emoticons/wassat.png' - }, - hidden: { - ':whistling:': 'emoticons/whistling.png', - ':love:': 'emoticons/wub.png' - } - }, - /** * Width of the editor. Set to null for automatic with * * @type {?number} */ - width: null, + width: '100%', /** * Height of the editor including toolbar. Set to null for automatic @@ -317,7 +298,7 @@ export default { * * @type {string} */ - plugins: '', + plugins: 'undo,dragdrop', /** * z-index to set the editor container to. Needed for jQuery UI dialog. @@ -340,7 +321,7 @@ export default { * * @type {boolean} */ - disableBlockRemove: false, + disableBlockRemove: true, /** * Array of allowed URL (should be either strings or regex) for iframes. @@ -363,14 +344,14 @@ export default { * * @type {Object} */ - parserOptions: { }, + parserOptions: {}, /** * CSS that will be added to the to dropdown menu (eg. z-index) * * @type {Object} */ - dropDownCss: { }, + dropDownCss: {}, /** * An array of tags that are allowed in the editor content. @@ -395,18 +376,35 @@ export default { * * @type {Array} */ - allowedAttributes: [], + allowedAttributes: ['contenteditable'], + + /** + * Url for the BBCode Extensions json + * + * @type {string} + */ + extensionsUrl: '', /** - * Default path for the script files - * - * @type {string} - */ - basePath: 'minified', + * Application root url + * + * @type {string} + */ + root: '', + /** - * The input format - * - * @type {string} - */ - format: 'bbcode' + * Attachments preview url + * + * @type {string} + */ + attachmentsPreviewUrl: '', + + /** + * Albums preview url + * + * @type {string} + */ + albumsPreviewUrl: '', + + onToggleMode: undefined }; diff --git a/src/lib/dom.js b/src/lib/dom.js index cc94ea10f..120b1d55a 100644 --- a/src/lib/dom.js +++ b/src/lib/dom.js @@ -64,6 +64,7 @@ export function createElement(tag, attributes, context) { utils.each(attributes || {}, function (key, value) { if (key === 'style') { node.style.cssText = value; + } else if (key in node) { node[key] = value; } else { @@ -192,7 +193,7 @@ export function on(node, events, selector, fn, capture) { var handler; if (utils.isString(selector)) { - handler = fn['_sce-event-' + event + selector] || function (e) { + handler = fn[`_sce-event-${event}${selector}`] || function (e) { var target = e.target; while (target && target !== node) { if (is(target, selector)) { @@ -204,7 +205,7 @@ export function on(node, events, selector, fn, capture) { } }; - fn['_sce-event-' + event + selector] = handler; + fn[`_sce-event-${event}${selector}`] = handler; } else { handler = selector; capture = fn; @@ -230,7 +231,7 @@ export function off(node, events, selector, fn, capture) { var handler; if (utils.isString(selector)) { - handler = fn['_sce-event-' + event + selector]; + handler = fn[`_sce-event-${event}${selector}`]; } else { handler = selector; capture = fn; @@ -323,13 +324,14 @@ export function css(node, rule, value) { return node.nodeType === 1 ? getComputedStyle(node)[rule] : null; } - utils.each(rule, function (key, value) { - css(node, key, value); - }); + utils.each(rule, + function(key, value) { + css(node, key, value); + }); } else { // isNaN returns false for null, false and empty strings // so need to check it's truthy or 0 - var isNumeric = (value || value === 0) && !isNaN(value); + const isNumeric = (value || value === 0) && !isNaN(value); node.style[rule] = isNumeric ? value + 'px' : value; } } @@ -348,25 +350,26 @@ export function css(node, rule, value) { * @return {Object|undefined} */ export function data(node, key, value) { - var argsLength = arguments.length; + const argsLength = arguments.length; var data = {}; if (node.nodeType === ELEMENT_NODE) { if (argsLength === 1) { - utils.each(node.attributes, function (_, attr) { - if (/^data\-/i.test(attr.name)) { - data[attr.name.substr(5)] = attr.value; - } - }); + utils.each(node.attributes, + function(_, attr) { + if (/^data\-/i.test(attr.name)) { + data[attr.name.substr(5)] = attr.value; + } + }); return data; } if (argsLength === 2) { - return attr(node, 'data-' + key); + return attr(node, `data-${key}`); } - attr(node, 'data-' + key, String(value)); + attr(node, `data-${key}`, String(value)); } } @@ -381,7 +384,8 @@ export function is(node, selector) { var result = false; if (node && node.nodeType === ELEMENT_NODE) { - result = (node.matches || node.msMatchesSelector || + result = (node.matches || + node.msMatchesSelector || node.webkitMatchesSelector).call(node, selector); } @@ -409,7 +413,7 @@ export function contains(node, child) { * @returns {?HTMLElement} */ export function previousElementSibling(node, selector) { - var prev = node.previousElementSibling; + const prev = node.previousElementSibling; if (selector && prev) { return is(prev, selector) ? prev : null; @@ -441,7 +445,7 @@ function classes(node) { * @returns {boolean} */ export function hasClass(node, className) { - return is(node, '.' + className); + return is(node, `.${className}`); } /** @@ -449,7 +453,7 @@ export function hasClass(node, className) { * @param {string} className */ export function addClass(node, className) { - var classList = classes(node); + const classList = classes(node); if (classList.indexOf(className) < 0) { classList.push(className); @@ -463,7 +467,7 @@ export function addClass(node, className) { * @param {string} className */ export function removeClass(node, className) { - var classList = classes(node); + const classList = classes(node); utils.arrayRemove(classList, className); @@ -502,9 +506,9 @@ export function toggleClass(node, className, state) { */ export function width(node, value) { if (utils.isUndefined(value)) { - var cs = getComputedStyle(node); - var padding = toFloat(cs.paddingLeft) + toFloat(cs.paddingRight); - var border = toFloat(cs.borderLeftWidth) + toFloat(cs.borderRightWidth); + const cs = getComputedStyle(node); + const padding = toFloat(cs.paddingLeft) + toFloat(cs.paddingRight); + const border = toFloat(cs.borderLeftWidth) + toFloat(cs.borderRightWidth); return node.offsetWidth - padding - border; } @@ -521,9 +525,9 @@ export function width(node, value) { */ export function height(node, value) { if (utils.isUndefined(value)) { - var cs = getComputedStyle(node); - var padding = toFloat(cs.paddingTop) + toFloat(cs.paddingBottom); - var border = toFloat(cs.borderTopWidth) + toFloat(cs.borderBottomWidth); + const cs = getComputedStyle(node); + const padding = toFloat(cs.paddingTop) + toFloat(cs.paddingBottom); + const border = toFloat(cs.borderTopWidth) + toFloat(cs.borderBottomWidth); return node.offsetHeight - padding - border; } @@ -600,7 +604,7 @@ export function traverse(node, func, innermostFirst, siblingsOnly, reverse) { node = reverse ? node.lastChild : node.firstChild; while (node) { - var next = reverse ? node.previousSibling : node.nextSibling; + const next = reverse ? node.previousSibling : node.nextSibling; if ( (!innermostFirst && func(node) === false) || @@ -635,8 +639,8 @@ export function rTraverse(node, func, innermostFirst, siblingsOnly) { export function parseHTML(html, context) { context = context || document; - var ret = context.createDocumentFragment(); - var tmp = createElement('div', {}, context); + const ret = context.createDocumentFragment(); + const tmp = createElement('div', {}, context); tmp.innerHTML = html; @@ -723,7 +727,7 @@ export function canHaveChildren(node) { // Source: http://www.w3.org/TR/html5/syntax.html#void-elements return ('|iframe|area|base|basefont|br|col|frame|hr|img|input|wbr' + '|isindex|link|meta|param|command|embed|keygen|source|track|' + - 'object|').indexOf('|' + node.nodeName.toLowerCase() + '|') < 0; + 'object|').indexOf(`|${node.nodeName.toLowerCase()}|`) < 0; } /** @@ -734,8 +738,8 @@ export function canHaveChildren(node) { * @return {boolean} */ export function isInline(elm, includeCodeAsBlock) { - var tagName, - nodeType = (elm || {}).nodeType || TEXT_NODE; + var tagName; + const nodeType = (elm || {}).nodeType || TEXT_NODE; if (nodeType !== ELEMENT_NODE) { return nodeType === TEXT_NODE; @@ -747,7 +751,7 @@ export function isInline(elm, includeCodeAsBlock) { return !includeCodeAsBlock; } - return blockLevelList.indexOf('|' + tagName + '|') < 0; + return blockLevelList.indexOf(`|${tagName}|`) < 0; } /** @@ -790,27 +794,27 @@ export function isEmpty(node) { */ export function fixNesting(node) { traverse(node, function (node) { - var list = 'ul,ol', - isBlock = !isInline(node, true) && node.nodeType !== COMMENT_NODE, - parent = node.parentNode; + const list = 'ul,ol'; + const isBlock = !isInline(node, true) && node.nodeType !== COMMENT_NODE; + var parent = node.parentNode; // Any blocklevel element inside an inline element needs fixing. // Also

tags that contain blocks should be fixed if (isBlock && (isInline(parent, true) || parent.tagName === 'P')) { // Find the last inline parent node - var lastInlineParent = node; + let lastInlineParent = node; while (isInline(lastInlineParent.parentNode, true) || lastInlineParent.parentNode.tagName === 'P') { lastInlineParent = lastInlineParent.parentNode; } - var before = extractContents(lastInlineParent, node); - var middle = node; + const before = extractContents(lastInlineParent, node); + const middle = node; // Clone inline styling and apply it to the blocks children while (parent && isInline(parent, true)) { if (parent.nodeType === ELEMENT_NODE) { - var clone = parent.cloneNode(); + const clone = parent.cloneNode(); while (middle.firstChild) { appendChild(clone, middle.firstChild); } @@ -831,7 +835,7 @@ export function fixNesting(node) { // Fix invalid nested lists which should be wrapped in an li tag if (isBlock && is(node, list) && is(node.parentNode, list)) { - var li = previousElementSibling(node, 'li'); + let li = previousElementSibling(node, 'li'); if (!li) { li = createElement('li'); @@ -880,11 +884,12 @@ export function getSibling(node, previous) { */ export function removeWhiteSpace(root) { var nodeValue, nodeType, next, previous, previousSibling, - nextNode, trimStart, - cssWhiteSpace = css(root, 'whiteSpace'), - // Preserve newlines if is pre-line - preserveNewLines = /line$/i.test(cssWhiteSpace), - node = root.firstChild; + nextNode, trimStart + // Preserve newlines if is pre-line + ; + const cssWhiteSpace = css(root, 'whiteSpace'); + const preserveNewLines = /line$/i.test(cssWhiteSpace); + var node = root.firstChild; // Skip pre & pre-wrap with any vendor prefix if (/pre(\-wrap)?$/i.test(cssWhiteSpace)) { @@ -970,7 +975,7 @@ export function removeWhiteSpace(root) { * @return {DocumentFragment} */ export function extractContents(startNode, endNode) { - var range = startNode.ownerDocument.createRange(); + const range = startNode.ownerDocument.createRange(); range.setStartBefore(startNode); range.setEndAfter(endNode); @@ -1008,8 +1013,8 @@ export function getOffset(node) { * @return {string} */ export function getStyle(elm, property) { - var styleValue, - elmStyle = elm.style; + var styleValue; + const elmStyle = elm.style; if (!cssPropertyNameCache[property]) { cssPropertyNameCache[property] = camelCase(property); @@ -1043,7 +1048,7 @@ export function getStyle(elm, property) { * @return {boolean} */ export function hasStyle(elm, property, values) { - var styleValue = getStyle(elm, property); + const styleValue = getStyle(elm, property); if (!styleValue) { return false; @@ -1068,7 +1073,7 @@ function stylesMatch(nodeA, nodeB) { } while (i--) { - var prop = nodeA.style[i]; + const prop = nodeA.style[i]; if (nodeA.style[prop] !== nodeB.style[prop]) { return false; } @@ -1092,8 +1097,8 @@ function attributesMatch(nodeA, nodeB) { } while (i--) { - var prop = nodeA.attributes[i]; - var notMatches = prop.name === 'style' ? + const prop = nodeA.attributes[i]; + const notMatches = prop.name === 'style' ? !stylesMatch(nodeA, nodeB) : prop.value !== attr(nodeB, prop.name); @@ -1182,13 +1187,14 @@ export function merge(node) { var isBold = /B|STRONG/.test(tagName); var isItalic = tagName === 'EM'; - while (parent && isInline(parent) && + while (parent && + isInline(parent) && (!isBold || /bold|700/i.test(css(parent, 'fontWeight'))) && (!isItalic || css(parent, 'fontStyle') === 'italic')) { // Remove if parent match if ((parent.tagName === tagName || - (isBold && /B|STRONG/.test(parent.tagName))) && + (isBold && /B|STRONG/.test(parent.tagName))) && attributesMatch(parent, node)) { removeKeepChildren(node); break; diff --git a/src/lib/escape.js b/src/lib/escape.js index cc78c2ec8..5a551601f 100644 --- a/src/lib/escape.js +++ b/src/lib/escape.js @@ -46,14 +46,15 @@ export function entities(str, noQuotes) { }; if (noQuotes !== false) { - replacements['"'] = '"'; + replacements['"'] = '"'; replacements['\''] = '''; - replacements['`'] = '`'; + replacements['`'] = '`'; } - str = str.replace(/ {2}|\r\n|[&<>\r\n'"`]/g, function (match) { - return replacements[match] || match; - }); + str = str.replace(/ {2}|\r\n|[&<>\r\n'"`]/g, + function(match) { + return replacements[match] || match; + }); return str; }; @@ -84,21 +85,21 @@ export function entities(str, noQuotes) { * @since 1.4.5 */ export function uriScheme(url) { - var path, - // If there is a : before a / then it has a scheme - hasScheme = /^[^\/]*:/i, - location = window.location; + const hasScheme = /^[^\/]*:/i; + const location = window.location; // Has no scheme or a valid scheme if ((!url || !hasScheme.test(url)) || VALID_SCHEME_REGEX.test(url)) { return url; } - path = location.pathname.split('/'); + const path = location.pathname.split('/'); path.pop(); - return location.protocol + '//' + + return location.protocol + + '//' + location.host + - path.join('/') + '/' + + path.join('/') + + '/' + url; }; diff --git a/src/lib/templates.js b/src/lib/templates.js index 563c4279a..78b619937 100644 --- a/src/lib/templates.js +++ b/src/lib/templates.js @@ -10,77 +10,129 @@ import * as escape from './escape.js'; var _templates = { html: '' + - '' + + '' + '' + - '' + - '' + + '' + + '{styles}' + '' + - '

' + - '', + '

' + + '' + + '', - toolbarButton: '', + + toolbarButton: '' + - '
{dispName}
', + ' ', + + codeOpt: '{languageName}', - emoticon: '', + extensionOpt: '{extension}', - fontOpt: '{font}', - sizeOpt: '{size}', + albums: + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
    ' + + '
    ' + + '
    ', + + attachments: + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
      ' + + '
      ' + + '
      ' + + '' + + '
      ' + + '
      ', + pastetext: - '
      ' + - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '' + + '
      ', table: - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '
      ', image: - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '
      ' + + '
      ' + + '
      ', email: - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '
      ' + + '
      ' + + '' + + '
      ', link: - '
      ' + - '
      ' + - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '
      ' + + '
      ' + + '
      ', + + mediaMenu: + '
      ' + + '
      ' + + '' + + '
      ', youtubeMenu: - '
      ' + - '
      ' + - '
      ' + - '
      ', + '
      ' + + '
      ' + + '' + + '
      ', + + instagramMenu: + '
      ' + + '
      ' + + '' + + '
      ', + + facebookMenu: + '
      ' + + '
      ' + + '' + + '
      ', + + facebook: + '
      ', + + instagram: + '
      ', youtube: - '' + '
      ', + + vimeo: + '
      ' }; /** @@ -95,12 +147,13 @@ var _templates = { * @returns {string|DocumentFragment} * @private */ -export default function (name, params, createHtml) { +export default function(name, params, createHtml) { var template = _templates[name]; - Object.keys(params).forEach(function (name) { + Object.keys(params).forEach(function(name) { template = template.replace( - new RegExp(escape.regex('{' + name + '}'), 'g'), params[name] + new RegExp(escape.regex(`{${name}}`), 'g'), + params[name] ); }); diff --git a/src/lib/utils.js b/src/lib/utils.js index 37897f4ef..8a0d915f4 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -52,24 +52,25 @@ export function isEmptyObject(obj) { * @return {Object} */ export function extend(targetArg, sourceArg) { - var isTargetBoolean = targetArg === !!targetArg; - var i = isTargetBoolean ? 2 : 1; - var target = isTargetBoolean ? sourceArg : targetArg; - var isDeep = isTargetBoolean ? targetArg : false; + const isTargetBoolean = targetArg === !!targetArg; + var i = isTargetBoolean ? 2 : 1; + const target = isTargetBoolean ? sourceArg : targetArg; + const isDeep = isTargetBoolean ? targetArg : false; function isObject(value) { - return value !== null && typeof value === 'object' && + return value !== null && + typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype; } for (; i < arguments.length; i++) { - var source = arguments[i]; + const source = arguments[i]; // Copy all properties for jQuery compatibility /* eslint guard-for-in: off */ - for (var key in source) { - var targetValue = target[key]; - var value = source[key]; + for (let key in source) { + const targetValue = target[key]; + const value = source[key]; // Skip undefined values to match jQuery if (isUndefined(value)) { @@ -81,13 +82,13 @@ export function extend(targetArg, sourceArg) { continue; } - var isValueObject = isObject(value); - var isValueArray = Array.isArray(value); + const isValueObject = isObject(value); + const isValueArray = Array.isArray(value); if (isDeep && (isValueObject || isValueArray)) { // Can only merge if target type matches otherwise create // new target to merge into - var isSameType = isObject(targetValue) === isValueObject && + const isSameType = isObject(targetValue) === isValueObject && Array.isArray(targetValue) === isValueArray; target[key] = extend( @@ -111,7 +112,7 @@ export function extend(targetArg, sourceArg) { * @param {*} item */ export function arrayRemove(arr, item) { - var i = arr.indexOf(item); + const i = arr.indexOf(item); if (i > -1) { arr.splice(i, 1); @@ -126,11 +127,11 @@ export function arrayRemove(arr, item) { */ export function each(obj, fn) { if (Array.isArray(obj) || 'length' in obj && isNumber(obj.length)) { - for (var i = 0; i < obj.length; i++) { + for (let i = 0; i < obj.length; i++) { fn(i, obj[i]); } } else { - Object.keys(obj).forEach(function (key) { + Object.keys(obj).forEach(function(key) { fn(key, obj[key]); }); } diff --git a/src/plugins/alternative-lists.js b/src/plugins/alternative-lists.js deleted file mode 100644 index 838bd86ea..000000000 --- a/src/plugins/alternative-lists.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - * SCEditor Inline-Code Plugin for BBCode format - * http://www.sceditor.com/ - * - * Copyright (C) 2011-2013, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @fileoverview SCEditor alternative lists plugin - * This plugin implements phpBB style of the lists: - * [list] - * [*]item - * [*]item - * [/list] - * @author Alex Betis - */ - -(function (sceditor) { - 'use strict'; - - var utils = sceditor.utils; - - function isFunction(fn) { - return typeof fn === 'function'; - } - - sceditor.plugins['alternative-lists'] = function () { - var base = this; - - /** - * Private functions - * @private - */ - var bulletHandler; - var orderedHandler; - var insertListTag; - - base.init = function () { - var opts = this.opts; - - // Enable for BBCode only - if (opts.format && opts.format !== 'bbcode') { - return; - } - - // Override only txtExec implementation - sceditor.command.get('orderedlist').txtExec = orderedHandler; - sceditor.command.get('bulletlist').txtExec = bulletHandler; - - // Override current implementation - sceditor.formats.bbcode.set('list', { - breakStart: true, - isInline: false, - skipLastLineBreak: true, - html: function (token, attrs, content) { - var listType = 'disc'; - var toHtml = null; - - if (attrs.defaultattr) { - listType = attrs.defaultattr; - } - - if (listType === '1') { - // This listType belongs to orderedList (OL) - toHtml = sceditor.formats.bbcode.get('ol').html; - } else { - // unknown listType, use default bullet list behavior - toHtml = sceditor.formats.bbcode.get('ul').html; - } - - if (isFunction(toHtml)) { - return toHtml.call(this, token, attrs, content); - } else { - token.attrs['0'] = content; - return sceditor.formats.bbcode.formatBBCodeString( - toHtml, token.attrs); - } - } - }); - - sceditor.formats.bbcode.set('ul', { - tags: { - ul: null - }, - breakStart: true, - isInline: false, - skipLastLineBreak: true, - format: '[list]{0}[/list]', - html: '
        {0}
      ' - }); - - sceditor.formats.bbcode.set('ol', { - tags: { - ol: null - }, - breakStart: true, - isInline: false, - skipLastLineBreak: true, - format: '[list=1]{0}[/list]', - html: '
        {0}
      ' - }); - - sceditor.formats.bbcode.set('li', { - tags: { - li: null - }, - isInline: false, - closedBy: ['/ul', '/ol', '/list', '*', 'li'], - format: '[*]{0}', - html: '
    • {0}
    • ' - }); - - sceditor.formats.bbcode.set('*', { - isInline: false, - excludeClosing: true, - closedBy: ['/ul', '/ol', '/list', '*', 'li'], - html: '
    • {0}
    • ' - }); - }; - - insertListTag = function (editor, listType, selected) { - var content = ''; - - utils.each(selected.split(/\r?\n/), function (item) { - content += (content ? '\n' : '') + - '[*]' + item; - }); - - if (listType === '') { - editor.insertText('[list]\n' + content + '\n[/list]'); - } else { - editor.insertText('[list=' + listType + ']\n' + content + - '\n[/list]'); - } - }; - - /** - * Function for the txtExec and exec properties - * - * @param {node} caller - * @private - */ - orderedHandler = function (caller, selected) { - var editor = this; - - insertListTag(editor, '1', selected); - }; - - bulletHandler = function (caller, selected) { - var editor = this; - - insertListTag(editor, '', selected); - }; - - }; -})(sceditor); diff --git a/src/plugins/autosave.js b/src/plugins/autosave.js deleted file mode 100644 index 73d846409..000000000 --- a/src/plugins/autosave.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * SCEditor AutoSave Plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @author Sam Clarke - */ -(function (sceditor) { - 'use strict'; - - var defaultKey = 'sce-autodraft-' + location.pathname + location.search; - - function clear(key) { - localStorage.removeItem(key || defaultKey); - } - - sceditor.plugins.autosave = function () { - var base = this; - var editor; - var isLoading = false; - var storageKey = defaultKey; - // 86400000 = 24 hrs (24 * 60 * 60 * 1000) - var expires = 86400000; - var saveHandler = function (value) { - localStorage.setItem(storageKey, JSON.stringify(value)); - }; - var loadHandler = function () { - return JSON.parse(localStorage.getItem(storageKey)); - }; - - function gc() { - for (var i = 0; i < localStorage.length; i++) { - var key = localStorage.key(i); - - if (/^sce\-autodraft\-/.test(key)) { - var item = JSON.parse(localStorage.getItem(storageKey)); - if (item && item.time < Date.now() - expires) { - clear(key); - } - } - } - } - - base.init = function () { - editor = this; - var opts = editor.opts && editor.opts.autosave || {}; - - saveHandler = opts.save || saveHandler; - loadHandler = opts.load || loadHandler; - storageKey = opts.storageKey || storageKey; - expires = opts.expires || expires; - - gc(); - }; - - base.signalReady = function () { - // Add submit event listener to clear autosave - var parent = editor.getContentAreaContainer(); - while (parent) { - if (/form/i.test(parent.nodeName)) { - parent.addEventListener( - 'submit', clear.bind(null, storageKey), true - ); - break; - } - - parent = parent.parentNode; - } - - var state = loadHandler(); - if (state) { - isLoading = true; - editor.sourceMode(state.sourceMode); - editor.val(state.value, false); - editor.focus(); - - if (state.sourceMode) { - editor.sourceEditorCaret(state.caret); - } else { - editor.getRangeHelper().restoreRange(); - } - isLoading = false; - } else { - saveHandler({ - caret: this.sourceEditorCaret(), - sourceMode: this.sourceMode(), - value: editor.val(null, false), - time: Date.now() - }); - } - }; - - base.signalValuechangedEvent = function (e) { - if (!isLoading) { - saveHandler({ - caret: this.sourceEditorCaret(), - sourceMode: this.sourceMode(), - value: e.detail.rawValue, - time: Date.now() - }); - } - }; - }; - - sceditor.plugins.autosave.clear = clear; -}(sceditor)); diff --git a/src/plugins/autoyoutube.js b/src/plugins/autoyoutube.js deleted file mode 100644 index 59e3c4993..000000000 --- a/src/plugins/autoyoutube.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * SCEditor Auto Youtube Plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2016, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @author Sam Clarke - */ -(function (document, sceditor) { - 'use strict'; - - var dom = sceditor.dom; - - /* - (^|\s) Start of line or space - (?:https?:\/\/)? Optional scheme like http:// - (?:www\.)? Optional www. prefix - (?: - youtu\.be\/ Ends with .be/ so whatever comes next is the ID - | - youtube\.com\/watch\?v= Matches the .com version - ) - ([^"&?\/ ]{11}) The actual YT ID - (?:\&[\&_\?0-9a-z\#]+)? Any extra URL params - (\s|$) End of line or space - */ - var ytUrlRegex = /(^|\s)(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/watch\?v=)([^"&?\/ ]{11})(?:\&[\&_\?0-9a-z\#]+)?(\s|$)/i; - - function youtubeEmbedCode(id) { - return ''; - } - - function convertYoutubeLinks(parent, isRoot) { - var node = parent.firstChild; - var wholeContent = (parent.textContent || ''); - - // Don't care about whitespace if is the root node - if (isRoot) { - wholeContent = wholeContent.trim(); - } - - var match = wholeContent.match(ytUrlRegex); - // Whole content match so only return URL embed - if (wholeContent === wholeContent.trim() && match && - match[0].length === wholeContent.length) { - dom.removeAttr(parent, 'style'); - dom.removeAttr(parent, 'class'); - parent.innerHTML = youtubeEmbedCode(match[2]); - return; - } - - while (node) { - // 3 is TextNodes - if (node.nodeType === 3) { - var text = node.nodeValue; - var nodeParent = node.parentNode; - - if ((match = text.match(ytUrlRegex))) { - nodeParent.insertBefore(document.createTextNode( - text.substr(0, match.index) + match[1] - ), node); - - nodeParent.insertBefore( - dom.parseHTML(youtubeEmbedCode(match[2])), node - ); - - node.nodeValue = match[3] + - text.substr(match.index + match[0].length); - } - } else { - // TODO: Make this tag configurable. - if (!dom.is(node, 'code')) { - convertYoutubeLinks(node); - } - } - - node = node.nextSibling; - } - }; - - sceditor.plugins.autoyoutube = function () { - this.signalPasteRaw = function (data) { - // TODO: Make this tag configurable. - // Skip code tags - if (dom.closest(this.currentNode(), 'code')) { - return; - } - - if (data.html || data.text) { - var node = document.createElement('div'); - - node.innerHTML = data.html || - sceditor.escapeEntities(data.text); - - convertYoutubeLinks(node, true); - - data.html = node.innerHTML; - } - }; - }; -})(document, sceditor); diff --git a/src/plugins/dragdrop.js b/src/plugins/dragdrop.js index b050309bb..bf3696da8 100644 --- a/src/plugins/dragdrop.js +++ b/src/plugins/dragdrop.js @@ -9,7 +9,7 @@ * * @author Sam Clarke */ -(function (sceditor) { +(function(sceditor) { 'use strict'; /** @@ -50,12 +50,12 @@ function base64DataUriToBlob(url) { // 5 is length of "data:" prefix - var mime = url.substr(5, url.indexOf(';') - 5); - var data = atob(url.substr(url.indexOf(',') + 1)); + const mime = url.substr(5, url.indexOf(';') - 5); + const data = atob(url.substr(url.indexOf(',') + 1)); /* global Uint8Array */ - var binary = new Uint8Array(data.length); + const binary = new Uint8Array(data.length); - for (var i = 0; i < data.length; i++) { + for (let i = 0; i < data.length; i++) { binary[i] = data[i].charCodeAt(0); } @@ -66,13 +66,13 @@ } } - sceditor.plugins.dragdrop = function () { + sceditor.plugins.dragdrop = function() { if (!isSupported) { return; } - var base = this; - var opts; + const base = this; + var opts; var editor; var handleFile; var container; @@ -92,24 +92,26 @@ } } - function isAllowed(file) { + function isAllowed() { // FF sets type to application/x-moz-file until it has been dropped - if (file.type !== 'application/x-moz-file' && opts.allowedTypes && + /*if (file.type !== 'application/x-moz-file' && opts.allowedTypes && opts.allowedTypes.indexOf(file.type) < 0) { return false; } - return opts.isAllowed ? opts.isAllowed(file) : true; + return opts.isAllowed ? opts.isAllowed(file) : true;*/ + + return true; }; function createHolder(toReplace) { var placeholder = document.createElement('img'); placeholder.src = loadingGif; placeholder.className = 'sceditor-ignore'; - placeholder.id = 'sce-dragdrop-' + placeholderId++; + placeholder.id = `sce-dragdrop-${placeholderId++}`; function replace(html) { - var node = editor + const node = editor .getBody() .ownerDocument .getElementById(placeholder.id); @@ -123,7 +125,7 @@ } } - return function () { + return function() { if (toReplace) { toReplace.parentNode.replaceChild(placeholder, toReplace); } else { @@ -131,7 +133,7 @@ } return { - insert: function (html) { + insert: function(html) { replace(html); }, cancel: replace @@ -140,10 +142,10 @@ } function handleDragOver(e) { - var dt = e.dataTransfer; - var files = dt.files.length || !dt.items ? dt.files : dt.items; + const dt = e.dataTransfer; + const files = dt.files.length || !dt.items ? dt.files : dt.items; - for (var i = 0; i < files.length; i++) { + for (let i = 0; i < files.length; i++) { // Dragging a string should be left to default if (files[i].kind === 'string') { return; @@ -155,12 +157,12 @@ } function handleDrop(e) { - var dt = e.dataTransfer; - var files = dt.files.length || !dt.items ? dt.files : dt.items; + const dt = e.dataTransfer; + const files = dt.files.length || !dt.items ? dt.files : dt.items; hideCover(); - for (var i = 0; i < files.length; i++) { + for (let i = 0; i < files.length; i++) { // Dragging a string should be left to default if (files[i].kind === 'string') { return; @@ -174,7 +176,7 @@ e.preventDefault(); } - base.signalReady = function () { + base.signalReady = function() { editor = this; opts = editor.opts.dragdrop || {}; handleFile = opts.handleFile; @@ -182,9 +184,8 @@ container = editor.getContentAreaContainer().parentNode; cover = container.appendChild(sceditor.dom.parseHTML( - '' + // eslint-disable-next-line quotes + `` ).firstChild); container.addEventListener('dragover', handleDragOver); @@ -196,17 +197,17 @@ editor.getBody().addEventListener('drop', hideCover); }; - base.signalPasteHtml = function (paste) { + base.signalPasteHtml = function(paste) { if (!('handlePaste' in opts) || opts.handlePaste) { - var div = document.createElement('div'); + const div = document.createElement('div'); div.innerHTML = paste.val; - var images = div.querySelectorAll('img'); - for (var i = 0; i < images.length; i++) { - var image = images[i]; + const images = div.querySelectorAll('img'); + for (let i = 0; i < images.length; i++) { + const image = images[i]; if (base64DataUri.test(image.src)) { - var file = base64DataUriToBlob(image.src); + const file = base64DataUriToBlob(image.src); if (file && isAllowed(file)) { handleFile(file, createHolder(image)); } else { diff --git a/src/plugins/emojis.js b/src/plugins/emojis.js deleted file mode 100644 index 404a82008..000000000 --- a/src/plugins/emojis.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * SCEditor Paragraph Formatting Plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2011-2024, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @fileoverview SCEditor Paragraph Formatting Plugin - * @author Sam Clarke - */ -/*global EmojiMart*/ -(function (sceditor) { - 'use strict'; - - sceditor.plugins.emojis = function () { - const base = this; - - /** - * Function for the exec and txtExec properties - * - * @param {node} caller - * @private - */ - var emojisCmd = function (caller) { - const editor = this, - content = document.createElement('div'), - emojis = editor.opts.emojis || [], - perLine = Math.sqrt(Object.keys(emojis).length); - - if (!emojis.length) { - const pickerOptions = { onEmojiSelect: handleSelect }; - const picker = new EmojiMart.Picker(pickerOptions); - - content.appendChild(picker); - } else { - var line = document.createElement('div'); - - sceditor.utils.each(emojis, - function (_, emoji) { - const emojiElem = document.createElement('span'); - - emojiElem.className = 'sceditor-option'; - emojiElem.style = 'cursor:pointer'; - - emojiElem.appendChild(document.createTextNode(emoji)); - - emojiElem.addEventListener('click', - function (e) { - editor.closeDropDown(true); - - editor.insert(e.target.innerHTML); - - e.preventDefault(); - }); - - if (line.children.length >= perLine) { - line = document.createElement('div'); - } - - content.appendChild(line); - - line.appendChild(emojiElem); - }); - } - - editor.createDropDown(caller, 'emojis', content); - - function handleSelect(emoji) { - editor.insert(emoji.native); - - editor.closeDropDown(true); - } - }; - - base.init = function () { - this.commands.emojis = { - exec: emojisCmd, - txtExec: emojisCmd, - tooltip: 'Insert emoji', - shortcut: 'Ctrl+E' - }; - }; - }; -})(sceditor); diff --git a/src/plugins/format.js b/src/plugins/format.js deleted file mode 100644 index bcf447649..000000000 --- a/src/plugins/format.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * SCEditor Paragraph Formatting Plugin - * http://www.sceditor.com/ - * - * Copyright (C) 2011-2013, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * @fileoverview SCEditor Paragraph Formatting Plugin - * @author Sam Clarke - */ -(function (sceditor) { - 'use strict'; - - sceditor.plugins.format = function () { - var base = this; - - /** - * Default tags - * @type {Object} - * @private - */ - var tags = { - p: 'Paragraph', - h1: 'Heading 1', - h2: 'Heading 2', - h3: 'Heading 3', - h4: 'Heading 4', - h5: 'Heading 5', - h6: 'Heading 6', - address: 'Address', - pre: 'Preformatted Text' - }; - - /** - * Private functions - * @private - */ - var insertTag, - formatCmd; - - - base.init = function () { - var opts = this.opts, - pOpts = opts.paragraphformat; - - // Don't enable if the BBCode plugin is enabled. - if (opts.format && opts.format === 'bbcode') { - return; - } - - if (pOpts) { - if (pOpts.tags) { - tags = pOpts.tags; - } - - if (pOpts.excludeTags) { - pOpts.excludeTags.forEach(function (val) { - delete tags[val]; - }); - } - } - - if (!this.commands.format) { - this.commands.format = { - exec: formatCmd, - txtExec: formatCmd, - tooltip: 'Format Paragraph' - }; - } - - if (opts.toolbar === sceditor.defaultOptions.toolbar) { - opts.toolbar = opts.toolbar.replace(',color,', - ',color,format,'); - } - }; - - /** - * Inserts the specified tag into the editor - * - * @param {sceditor} editor - * @param {string} tag - * @private - */ - insertTag = function (editor, tag) { - if (editor.sourceMode()) { - editor.insert('<' + tag + '>', ''); - } else { - editor.execCommand('formatblock', '<' + tag + '>'); - } - - }; - - /** - * Function for the exec and txtExec properties - * - * @param {node} caller - * @private - */ - formatCmd = function (caller) { - var editor = this, - content = document.createElement('div'); - - sceditor.utils.each(tags, function (tag, val) { - var link = document.createElement('a'); - link.className = 'sceditor-option'; - link.textContent = val.name || val; - link.addEventListener('click', function (e) { - editor.closeDropDown(true); - - if (val.exec) { - val.exec(editor); - } else { - insertTag(editor, tag); - } - - e.preventDefault(); - }); - - content.appendChild(link); - }); - - editor.createDropDown(caller, 'format', content); - }; - }; -})(sceditor); diff --git a/src/plugins/undo.js b/src/plugins/undo.js index 4eaca5280..abb1ed723 100644 --- a/src/plugins/undo.js +++ b/src/plugins/undo.js @@ -41,7 +41,7 @@ // Caret may not exist for the first state in Firefox if (state.caret) { - var range = editor.getRangeHelper().selectedRange(); + const range = editor.getRangeHelper().selectedRange(); setRangePositions(range, state.caret); editor.getRangeHelper().selectRange(range); } @@ -60,7 +60,7 @@ var origFn = obj[fn]; obj[fn] = function () { // sourceMode calls other patched methods so need to ignore them - var ignore = isInPatchedFn; + const ignore = isInPatchedFn; // Store caret position before any change is made if (!ignore && !isApplying && lastState && @@ -104,17 +104,30 @@ * Updates the last saved state with the editors current state */ function updateLastState() { - var sourceMode = editor.sourceMode(); + const sourceMode = editor.sourceMode(); lastState.caret = sourceMode ? editor.sourceEditorCaret() : getRangePositions(editor.getRangeHelper().selectedRange()); lastState.sourceMode = sourceMode; - lastState.value = sourceMode ? + + const value = sourceMode ? editor.getSourceEditorValue(false) : editor.getBody().innerHTML; + + const countField = document.getElementById('editor-Counter'), + maxLimit = editor.opts.maxLength; + + // Update counter + if (editor.val().length > maxLimit) { + base.undo(); + } else { + countField.textContent = maxLimit - editor.val().length; + } + + lastState.value = value; } base.init = function () { - // The this variable will be set to the instance of the editor + // this variable will be set to the instance of the editor // calling it, hence why the plugins "this" is saved to the base // variable. editor = this; @@ -231,7 +244,7 @@ // https://rawgit.com/w3c/input-events/v1/index.html#interface-InputEvent-Attributes // Most should cause a full undo item to be added so only need to // handle a few of them - var inputType = e.inputType; + const inputType = e.inputType; // Should ignore selection changes that occur because of input // events as already handling them @@ -311,8 +324,8 @@ */ function setRangePositions(range, positions) { try { - var startPositions = positions.startPositions; - var endPositions = positions.endPositions; + const startPositions = positions.startPositions; + const endPositions = positions.endPositions; range.setStart(positionsToNode(body, startPositions), startPositions[0]); @@ -332,7 +345,7 @@ * @returns {Array} */ function nodeToPositions(container, offset) { - var positions = [offset]; + const positions = [offset]; var node = container; while (node && node.tagName !== 'BODY') { @@ -363,7 +376,7 @@ * @returns {Node} */ function positionsToNode(node, positions) { - for (var i = positions.length - 1; node && i > 0; i--) { + for (let i = positions.length - 1; node && i > 0; i--) { node = node.childNodes[positions[i]]; } return node; diff --git a/src/plugins/v1compat.js b/src/plugins/v1compat.js deleted file mode 100644 index e67e5f3b1..000000000 --- a/src/plugins/v1compat.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Version 1 compatibility plugin - * - * Patches commands and BBCodes set with - * command.set and bbcode.set to wrap DOM - * node arguments in jQuery objects. - * - * Should only be used to ease migrating. - */ -(function (sceditor, $) { - 'use strict'; - - var plugins = sceditor.plugins; - - /** - * Patches a method to wrap and DOM nodes in a jQuery object - * @private - */ - function patchMethodArguments(fn) { - if (fn._scePatched) { - return fn; - } - - var patch = function () { - var args = []; - - for (var i = 0; i < arguments.length; i++) { - var arg = arguments[i]; - - if (arg && arg.nodeType) { - args.push($(arg)); - } else { - args.push(arg); - } - } - - return fn.apply(this, args); - }; - - patch._scePatched = true; - return patch; - } - - /** - * Patches a method to wrap any return value in a jQuery object - * @private - */ - function patchMethodReturn(fn) { - if (fn._scePatched) { - return fn; - } - - var patch = function () { - return $(fn.apply(this, arguments)); - }; - - patch._scePatched = true; - return patch; - } - - var oldSet = sceditor.command.set; - sceditor.command.set = function (name, cmd) { - if (cmd && typeof cmd.exec === 'function') { - cmd.exec = patchMethodArguments(cmd.exec); - } - - if (cmd && typeof cmd.txtExec === 'function') { - cmd.txtExec = patchMethodArguments(cmd.txtExec); - } - - return oldSet.call(this, name, cmd); - }; - - if (plugins.bbcode) { - var oldBBCodeSet = plugins.bbcode.bbcode.set; - plugins.bbcode.bbcode.set = function (name, bbcode) { - if (bbcode && typeof bbcode.format === 'function') { - bbcode.format = patchMethodArguments(bbcode.format); - } - - return oldBBCodeSet.call(this, name, bbcode); - }; - }; - - var oldCreate = sceditor.create; - sceditor.create = function (textarea, options) { - oldCreate.call(this, textarea, options); - - if (textarea && textarea._sceditor) { - var editor = textarea._sceditor; - - editor.getBody = patchMethodReturn(editor.getBody); - editor.getContentAreaContainer = - patchMethodReturn(editor.getContentAreaContainer); - } - }; -}(sceditor, jQuery)); diff --git a/src/themes/content/default.css b/src/themes/content/default.css deleted file mode 100644 index 4cf0e6886..000000000 --- a/src/themes/content/default.css +++ /dev/null @@ -1,85 +0,0 @@ -/*! SCEditor | (C) 2011-2013, Sam Clarke | sceditor.com/license */ -html, body, p, code:before, table { - margin: 0; - padding: 0; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 14px; - color: #111; - line-height: 1.25; - overflow: visible; -} -html { - height: 100%; -} -.ios { - /* Needed for iOS scrolling bug fix */ - overflow: auto; - -webkit-overflow-scrolling: touch; -} -.ios body { - /* Needed for iOS scrolling bug fix */ - position: relative; - overflow: auto; -} -body { - /* Needed to make sure body covers the whole editor and that - long lines don't cause horizontal scrolling */ - min-height: 100%; - word-wrap: break-word; -} - -body.placeholder::before { - content: attr(placeholder); - color: #555; - font-style: italic; -} - -ul, ol { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} - -table, td { - border: 1px dotted #000; - empty-cells: show; -} - -table td { - min-width: 5px; -} - -code { - display: block; - background: #f1f1f1; - white-space: pre; - padding: 1em; - text-align: left; - margin: .25em 0; - direction: ltr; -} - -blockquote { - background: #fff7d9; - margin: .25em 0; - border-left: .3em solid #f4e59f; - padding: .5em .5em .5em .75em; -} -blockquote cite { - font-weight: bold; - display: block; - font-size: 1em; - margin: 0 -.5em .25em -.75em; - padding: 0 .5em .15em .75em; - border-bottom: 1px solid #f4e59f; -} - -h1, h2, h3, h4, h5, h6 { - padding: 0; margin: 0; -} - -/* Prevent empty paragraphs from collapsing */ -div, p { - min-height: 1.25em; -} diff --git a/src/themes/default.less b/src/themes/default.less deleted file mode 100644 index 973337d88..000000000 --- a/src/themes/default.less +++ /dev/null @@ -1,13 +0,0 @@ -/*! SCEditor | (C) 2011-2016, Sam Clarke | sceditor.com/license */ -/** - * Default SCEditor - * http://www.sceditor.com/ - * - * Copyright (C) 2011-16, Sam Clarke - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ - -@import "icons/famfamfam.less"; -@import "inc/defaultbase.less"; diff --git a/src/themes/defaultdark.less b/src/themes/defaultdark.less deleted file mode 100644 index 37cffc233..000000000 --- a/src/themes/defaultdark.less +++ /dev/null @@ -1,31 +0,0 @@ -/*! SCEditor | (C) 2017, Sam Clarke | sceditor.com/license */ -/** - * Default SCEditor - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ - @import "icons/famfamfam.less"; - @import "inc/defaultbase.less"; - - div.sceditor-toolbar { - background: #5d5d5d; -} -div.sceditor-group { - background: #303030; - border-bottom: 1px solid #000; -} -.sceditor-button:hover, -.sceditor-button:active, -.sceditor-button.active { - background: #6b6b6b; -} -.sceditor-button svg { - fill: #fff; -} -.sceditor-button.disabled svg { - fill: #777; -} \ No newline at end of file diff --git a/src/themes/icons/famfamfam.less b/src/themes/icons/famfamfam.less deleted file mode 100644 index b47f130f8..000000000 --- a/src/themes/icons/famfamfam.less +++ /dev/null @@ -1,56 +0,0 @@ -// Where to find the famfamfam icon images -@famfamfam-image-location: "famfamfam.png"; - -div.sceditor-grip, .sceditor-button div { - background-image: url("@{famfamfam-image-location}"); - background-repeat: no-repeat; - width: 16px; - height: 16px; -} -.sceditor-button-youtube div { background-position: 0px 0px; } -.sceditor-button-link div { background-position: 0px -16px; } -.sceditor-button-unlink div { background-position: 0px -32px; } -.sceditor-button-underline div { background-position: 0px -48px; } -.sceditor-button-time div { background-position: 0px -64px; } -.sceditor-button-table div { background-position: 0px -80px; } -.sceditor-button-superscript div { background-position: 0px -96px; } -.sceditor-button-subscript div { background-position: 0px -112px; } -.sceditor-button-strike div { background-position: 0px -128px; } -.sceditor-button-source div { background-position: 0px -144px; } -.sceditor-button-size div { background-position: 0px -160px; } -.sceditor-button-rtl div { background-position: 0px -176px; } -.sceditor-button-right div { background-position: 0px -192px; } -.sceditor-button-removeformat div { background-position: 0px -208px; } -.sceditor-button-quote div { background-position: 0px -224px; } -.sceditor-button-print div { background-position: 0px -240px; } -.sceditor-button-pastetext div { background-position: 0px -256px; } -.sceditor-button-paste div { background-position: 0px -272px; } -.sceditor-button-outdent div { background-position: 0px -288px; } -.sceditor-button-orderedlist div { background-position: 0px -304px; } -.sceditor-button-maximize div { background-position: 0px -320px; } -.sceditor-button-ltr div { background-position: 0px -336px; } -.sceditor-button-left div { background-position: 0px -352px; } -.sceditor-button-justify div { background-position: 0px -368px; } -.sceditor-button-italic div { background-position: 0px -384px; } -.sceditor-button-indent div { background-position: 0px -400px; } -.sceditor-button-image div { background-position: 0px -416px; } -.sceditor-button-horizontalrule div { background-position: 0px -432px; } -.sceditor-button-format div { background-position: 0px -448px; } -.sceditor-button-font div { background-position: 0px -464px; } -.sceditor-button-emoticon div { background-position: 0px -480px; } -.sceditor-button-emojis div { background-position: 0px -660px; } -.sceditor-button-email div { background-position: 0px -496px; } -.sceditor-button-date div { background-position: 0px -512px; } -.sceditor-button-cut div { background-position: 0px -528px; } -.sceditor-button-copy div { background-position: 0px -544px; } -.sceditor-button-color div { background-position: 0px -560px; } -.sceditor-button-code div { background-position: 0px -576px; } -.sceditor-button-center div { background-position: 0px -592px; } -.sceditor-button-bulletlist div { background-position: 0px -608px; } -.sceditor-button-bold div { background-position: 0px -624px; } -div.sceditor-grip { - background-position: 0px -640px; - width: 10px; - height: 10px; -} -.rtl div.sceditor-grip { background-position: 0px -650px; } diff --git a/src/themes/icons/famfamfam.png b/src/themes/icons/famfamfam.png deleted file mode 100644 index ce0adb48ecdeea2a308bc00762db64e0fc4929bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12429 zcmX9^18^YC65behv2FWe<6`S#+qN&ZZ95m|V%xdcw(aEQueViGyEWU>(>uM>-Sc&a z$;*nt!D7P#001W;F0A-Y6TltNRf@=`gLgr+AC}KL%O{R*gcT`8v=k0{vEu)8v>J=xl+ ztO%$eg!b`kZsnkA6%YHAf~7Oy;kX!T^NeY8^_#BzF>xXRq}ybqDJzces}5|aeisk` zCkiw+!E%gG48DA774xfhwa?!7y_iB$_=XM!N^I|sRV>pk$Ww2Qlld4{P)S?Sf7p*g zt{wXncN#uqn<+*AjfdI7g!#5#!Ju|-KoXIWk^}3#Ea;#cGNwhUZtx3f%o}a zAB4AY+9``zTrY7lpNl(vxtAv~tuA5uAT2aT2ijanxVlrQ&w$N! zje#-=2C7VOA%^H%Cdj)B(5m2FF9L4aQ*dZLFjbEsT}#mVoI-XkjWcM>HAwnD-05{t zS{Fc{T(H&XAJjrB)QIj^EN>-z%vOk(#rBPrR}OEWZtm9$BnJohpj2YV#qCAs#l{Ek z?8PM%6`NxO075`QSWww*<=ordOX=6j=i|oOo{9O2)26D1#;8tivWQWfi26Df z5^9pWGa`l)_@aB3Jz}Qdkg?YoWsKz_V{uZ3pQ*1taRR&7U!uNV1xo(e z^+n2!Kg9+KV;nnmrMSX)+S)9WXOJ>5(Yp;FkuOtjKCOP8P601uE=~ZOqek6qTYwdy z>y*0UVc0T74KFPPOrkq}9MQcBLUS_t%g>*@Mh!=Oa}z7IfP0zfiv18+?^vP()un2W z!ze>4*ZAFwkQg-cIko2g+a_dxteH9L#V|MA?bJIg4rjyLzLJLOZV)c52BqSTD*O2zd47GrSWuxh9R#ld?Pz$i%mPLj_(%MgP z#A*CjW-2NNQekCbPP_Z9{nNc=%_TWkGgsj{os;i~OmKGMDbJ9AW2M_bNcmN^N zZ{wBf56``$9SrpG9EJ($u|RSz@`E|!-9RH@*^bwXHYkieG{m^LI8;Fo^0}-J*<{{_ z7J>>{n;lXh7U{IvSm4vgx9z=&d-yQh(`T_*2FKCD(jqo3A+J{bT)oZpoS5(P%~3fq z-22@q#PC*Sd)EaaZU{0Y8&K1YgXpPQfjx*)4wJt}azb#*_!5#Zs;fcnjt z?Sc3$cz2*JFIrobRyeov_SzGGw#|D9R4=kW5-2|%thHS@jLlorNo@Mx)XjPc2d0mY zPmpK1;ONR_W!ueo+3~yp{*_!PAuHSpC9~#5ipRf;gNwr;6C`w0RcU7bng!iBVjLEh zu34r#CAZC!WDIYE1?%4&jRYo{kkUl2Rn3+l0gP2w`jso!oZV=3I=WIJqTELLc)fa;K?*1ZB>M#uC3iKw&WKJoyOhAQY+dZTjG1=f8it~bYJWm z_M9-6AsaL_?F#Q0E71=v^{Wq0(Tm!t1>7nP;SgKme029j=cwhLa$38tSg^E1}$<@{AYJcfJ0JiyB!>nvHDiDJpLvt@&?9h9wo} zy4IR1c48@S-CdDdifn(~+}@-PAJ4EUkCooyq87{^c;i^gq=J#d)8-afJ@_;}^?T+_ z4=9|+YLS+6spj{dqmz5@w>;$d>%LFKvbPvD*~xs9Ttq8gr@ z{D1<~DwCP2yFR#<=jH-SOG~rrOXRvbZ8tmRGI{QgVF2Cuk8$B5#i*;owW7+Q`_cE5 zSw3*Th-f6F`(_>Y6D#+0$s%l|e)+ewFxisV5o=9bFh3U)Ar|~+O&uX2A#)!af+MHa zj^*WLXg$hxCKMo*&v3A8e9fw`pQ6XSG1|srHhT8-9^*{q76izh%;a>$?$&0@IFC3x zJ0oooqKEMNPsMWk&&TQ`-8f8!G>nRdg%#ZF)gF{*)z^#fz*q`{t`Q@qPRgj!Kb4M;`}qo0 z2BaL`n_-eRI`lEOutc3Emx+@kZ3C~1mcs|$`#GgQlU*2Jx=-Wvd}zTBnXzK?RKvjO zH;cAzUL=JUQi_2Fx{vLG-`1_z67-4m)Y-he^KKC!1A2BHT7)_)7f;Fb73}tR_<)QF zmw(%KdcB2ZAh>Ep(bV=_S*9LFr!EwpvM5;395DJdV|})DsWK`_T;;-4DIJh7_oV|? zbq~V}vp?z;%_VOtwde`V8a37x%Ni8RlshSI{B&)p!32DKIsrhX;+Gjl4d{kF2X6m- zdnU-%JH{o}0z3cdaVe%x(^JOCmK}<`b(>x1!Tjdub3#t5aE)u6lTu zlen?NW$+=t9Q|+`GvB98Se%@Yc_Uhz++WzD zd2|+LSYk3mjvtP7MK0dYa45lhYJbo8UB|_GUKuu+t@?)}e^QA=81K`ON~3e%FdM|; zQVGOTP8&Gw96g(up|ZdpYb1JqLfYDkp?-c$<-7@l3T(brmY~%p7*)wae2p=QnG|v; z1nNh=mt~52IH1}Pr~(NAA}HFS{h3x!40bWE=n23p%dbpWu_<;EeiBHwXg_Icw9d_X zu*`Mv>|4FdN6ombq^Jap1|i8F#H69)OuQOw<8mj=aT_9fQMl||fih*}#$PG+S6hOW zUe6-J!liMTR6iRhWho0@A?Qup=67)5*r96hLE)@rhtVV-uD1J{jUTMO6L^EEMPH_q zU|G_D^zY6$s62X}SamF?3ar7`@90|b!g_#5U^(2$4h ze~?Q`wtr4w<#jH9&%X6LP+^u8$O+Z7aqT`M~s-Cq)<3UFQIi zG%u7j%(q|<6ac-f)(nU^Bf=cl00GWk+Plf!IN%i=Kz1Pq4KJ~H2jL`wmPgtQXTigTMgv?3YMLp{y}Dn3u0k zru?};_r4wg1k@KyPag=|gkyjGXKGlNcE{=GUp`C3c=z&pukg{^1)KmhM7Z^{tE-s@ z-Ott^xVmSNndpuCmu2*|>`N-w{D2=xQHY?Q+pa|e!JCB$!7964>Z4HF)sYfDk>hx{ z4hdp0?Mh|Lc?N}1v^o*bOX6WT71AKDJW-@)F0mOW|KpnD>$pihf@9K(gR3;%W9_;P z#e@lSi|ggaHSuwkDf~EW`~s)pxr0Bcjh?y-&sd%Ds_t{?fJuE83+DIxUn!OsNQq@i zAi35{FADbXo&?@jo9%?~?RN-|(&kNZt60H;Kb6Kv9I%{UH#$6r!2Du09iSnw7N5!g zEijN0sXvXUF{_Rm)s;kvlGw_m6L?znbrkDR;nJO~>RhWcp7K43$z@>|+U*Ubf1K;B zSAcIYN9m{bpyS+jtPZfwm{i zD>g{~jh2Zo4ED4XjUX%?jhCE3R=W zzCc$}Q+giSEnzS=F`*_y9x+2W%(jqgsV==9H#w|sP4!2l#96ed<6aU|PbNEedG-3T z;H0$08a%EY2QR19x~e}c#)*NW*^(*#i16^I#6(n|t?u6etp??tvbgLvYxuyG8&4y7 z!ZB<8@|#CnT@?Tf9%~r$!}Y=oPVi)P|{^5nsv8Xg~)E|MmnJ$B-<{!&|z zJdV^bU-MV!>KaPQjSF8x>-ljtv-`MQbwEOdM628B6*q6<*>>AE7!0Ybs#?(6s&Qn6 zJZr`x$I8xL4a*7ou_+}QrOskDoqLm?Pt3>1_aPs%tMT8$#Fagzd@Ttd5z)4yTHlew z4_g^;6CXwS7%9@rJF`SIsoADF?U9iYg78f=*nv;2RwwiM`PS5bUrsR!($GVWL2O8P zk$rA~1(H|3tU%I=4d>FXwKbC4fkV5O`?CF3RKrBYLL3~vM5<=ls{M0Fj|CR8Kw;V< z10wqnqN<6L1^GXRTRHGaLj1KaL*L^Ni9sut-BO+HIlP|a+rri?yInM@Xn{38Q}}b; zGA?S5!gUKiWR|$Wbw;-C;jL}0A1SLcspBTi+8bG4AI5YiU1*Fdo5=x^k#$|t`xiD# zg~oGNhJ9vTc7MAsB!tD)jUxpRfD{mLt>vJQ%{;P0Yf#$ZHw_p2j^QC9Xj&j;N{=3x zTUQrv>#7{6bpi$jckIK7fr=VSWC6D+p`@v~cmb*RBo8cewix||{=v-bLFVk9h7;$Ktzr86Z>5L{_3nn?p*6vkQ{dZdasJha;;iIfz-$&ffw zsQy|`7Ezb8HToU}10bT&5O6wgi-pIcUR7z)ZAEnrhoRWC%!zC1HPC0Vc&jzV+lztu zWjYP42OYFeCZlISjhLvuj{RIvD?y!d{(mH!%N z#{)5b$df$Zeu#&8%LAZ8VV9Rr$0ZBZC$u(BA*EY+YrARgSU(FKUnD@$mAC`i3;wg5 zJ8()a&*Q{wa)@>_etGc;rc%5_>MONykLk27PRA5+RE6=-?!u256~0vH@NUjj0 zEm3FsJW(IpsFN;LqNcH&vS~yCKzQHV!adMQF6Ko@)%f+~8NPC`kfwM`V12@q8DPta>shAmqpPdYS*zxjzlPd@Twzjg1aB=u7N?gv8?n&vk{hh^*a#=(D8X5wyzVOL`!_G@9n{Ctk z%Y`BlW+QpMc0aU=>0C@G<10ZNR~&o2E3n2jAZ9(7gDg)MR~*<_{CAVmI@Rvgx=gr0 z)oxz%9PpbpZ5ga-DuH-U{87KkEZEzK7&!(9Q1XjGCrZCaE@>GrHiR16Bzp^gF?8dx z*`$06eiHneC_S^sKBxD%rA!mLWpC5@KAa!d!%|45`_fTo{b79&Y@Ro}bj>YSBlWt3 z4x^uSJ44*g!zP`V>l-=+!ott)^S>{dcs)X?Umd2W7B?<+-gO{uawzJ1=3z{=8vwem z9);MGpEmv_6p&cQK}0^2gz3Qf3ic|!f9{u;4<-SGI2cyyDS$(k#4f!V!bR)WXgjH7a{k+8l%*f( z^Je$BXDXNovW?anEGA&kv0@gMhQ}V1Hy+Gs(kh*0?hWD3L^*hKk6_&0_m=9-)_3iA zn<%#f!u~WnSVf+Ps8|k4X=iCRYq%c9NsS&*8$W3av!FB(YvLrGzHvH>gV(Fz-*`RQ zDb%p99rYLIRC4GZqTcO?{Q7t`oSr1jqtvol)W);HugnmW2u7X_CjnSc=H~-8Ag=_L zG;rw1^8PvuhwfcnMP19A(>?~RX}z<{q!SA&k)kSI?n;RwhcGxo-_ygmWjT{DpG4}= z_-ygf6Dv?ric{J~pe$uYVy?>3zxVMf8N}~wcAAeGwYHf|D7F zYvR#IT*Z9DvXLtS-jCFWiuo=oBTGk=*Ip@xnFMkf(S*){h_9n|XYKuK7CWBAq#UZR3nK0@44Qh@nclLOAy*Y-6WfYNqS0ezxdv(@ zB=H}rK4-vy+^0dXA@Ye-+0lah?RLAlHvX0Mb7;T#HE8+czj2unSq;0ZRVX0sXrw3q zQLuO#CY*LYJm%)yHEFtH{g9EI@*$VSdm(G4-NMv-gzm?1ODTHfL!ayc=jGVICAiC= zFrlos+umF3zf7?>L2zw`db4n0wh=eR9@n|6J2FL$IMLa%{|Y&V3l+D+D6*jsMr{Vq zOEy-%j<7wkuZO8jhN02q%}apZBm?l$y0cBRdf~#EH*c}7e3<_J8)WOK7KP|5&;bjn z#ar6l*|Kppa1s%`VtfI4j0ZKq7+NAPi$?*|iDk3wE!g_OYl7x-4n`<_#&ZB0M4d17 zty-DdsltoFO>g@jTL)Wl+lq5lFc+~O0Si8dOB8`qyK(`0j~S60aHXapE>YOMXntNO ziT7)VAYz7$-^_Y?d!g%$#9Tdu{ahAcXm0Ma>cu9flu+;)-FFrW|) zk+p2tw_P}q2y#N7Zx0zD{r)3Lx;ungwOJz? zL5tEk{}HQTooYDLIt>DagX1X#uG>I)aiP($yyOPTjwcc%BnZNz zaDq_3%7}o?*cZ9N={JGiH1}Fiq@_>Wn73S6ONz@g;h<058MRe1erSq*N-px&k96Pd z6qVMGkF1YgCHA352*2mY4PA34oIv=pc~QVm_Ru*gi_g2YD<&^eTSbS%Db_@)qii=5 z+3@e466(IAZ0Mjzcs^*MyTMuAO>gJ(-6~kT@~%kRad}Ica&rF{0tL_9}Q0>_0H-5e)4-xfraX^iOxAx66rgsQRGsxX=2UN&* zojzqXhyUp|xVrNt{EFy`LRa`Ehwk!n;r74wAO87K8TT~QmEp;Y%ookl!cq5joe>YC zFx-$HMI$VVJ!($HMGFJCxfif|M`eNOv@pN(uZDpGJhvhpg!l?)aQt@@!f|JPV)Xku z3KZepBvLQRcpl%BM@pF@BCTKkzPk&leu#ns*=zD+Al+ry2j^K+_nvQGJfwWys&hwf zSB@Tq;P=5a4MH-D%$7rpC3}HNuIZG?BPM~EC$*g{H~a7PSc`? zOIrsVO%rcqf;W=`1@9G>Gs;7XPD745!Mks%Wdgng#nQwE`e@j*vwi&${`4*!M0ax4 zVd9b2C7+}3&9TSJVMrAO&uM6g8KQ)hQRj4(-%Bp`gSk>y$QRWZHK=mL+?XkM3iy7+ z++C47M?o&9&ib1Kgz!)3f8yymu58)Wb?U>G+11lcQ|1%(v$6odNFD7z5@sZ#7{4UO zyvjcfQd{*YlfCl?f*O+4$Og!yon=;J(q<+&x$`IbRnw%dLEYLpsg=w}Ja962P|%@Y zl4>7GJE$^Sjh4f#**f7nHO>d2)GrnJ60N0*5csQK$}DeRvO}|*%!G8CJH}wZE~vkc ze5WvB%7uYpf_%;+e{P|t?)Qj!?0Emr_ox0<+s9FXEE)W~#7Nx|gg?s&f35>Q zx!<-dVpQQn2%f5ADwuRQaeWX+ee9~<(qTi)kPF0l`s%Dufz*kE^-ZtaiT)ZSK!+XV zYwzKVH*vdOE`1nR@Adx%gMv3WOZEbwA=XIzzX0kMAa~wkF@&tjmHvC*_>CJ+?C7sm zkM*!GI^4wASb11rok_lq;zpZ(aY&WaYH@B(+EhLHEc%T;;>)}#Dl7L#lt6p1#>FQj z22f$fg-=Vsuhe#^a` zusHnI=QL2|wg0EJ&Q`q+hUtTX|JqPHs^>7>=zNy=PV=IAH@XQ8SQiGq?jf}B?Y^=4 z?tZGifP%P@^kcCz_2nDK_d-ZZDph{GJ*&%kIEJ-`VcBl5Q!?=J(N72TC=qc-U2)ir zF>f+}Z;9y5{E)c5w(kw7J}3V-%XPz5dc3tqBXm#n5I2;a|I_AAkT)@-+ufdx1V6+y z|7!FefrsS7+(wOzKA>leqi;5T{k zssc}jjgwEhE=l==3M+oqp{ZkQd0l?Ep*Lrt{aYEe+UCi+iy&^ErK6=Ko5UL7%Q(ha(8r0mSOv%zwV zv*y3Ez0qzn8TfBa4$9m1p95N`;8qUjMLH<6B*DVd?I7%8!un+MpU)tPT#UE_GY-(g z6QlKP%*o_a1FnM5>Fir3#yK#nd&l*H|I#*;e)(gyuYxLK!^A&G_D;S`=+U2NlM@pO z*OBcS(;<=N%xI5vOzN?1`%M3)+D~{3WVGO z+xWE3LU_93LjW&<@jvI_iH?XhqANE361H<+8nHP@F$S1g0QFx4|6yVw7QGXH+K%d` zMgqQSFOKSN_NPah0JQe6dx~ojc-)05Pvzqo215k(cN0o~EPk&hH0KaHKE0k}yvAZB z{uTsWmY@T1)YOO#rm)^8^Pl#4wclR~7J#j9RZRbC0~+~kq+7?)I`?Uzm-fs!S^T19 zgM<}g>{04#T~*PxQ0&^f{kd|I`;)qrRl#DQH2s4W7A|GdNiDb7RG%y`R=)$v%50=3 z847=IC0ySiJpFAkcUA1kOVV1BW_@9^r$F)e;RD+ZQAwRxN|#1-w!l_%!x*Q~OPq$w zXpQLb2o=Cj^om=tmnJ*CsDD6C1!s&K;G5Y`j zc;EkO0W9<=5&l%IXe0JSRes^nP$7Rudyq zQOp>j*VxFRB(jhdk~vBGE*Uwv;PzNvUX6o8uw^suE<7l;8cghr7Zs5Le0H9uocM!H zY(_9>Ebo5sIhG?ii{4v)kuqUE$u9f!T&uqGK%>Ow*A_|~WLhar`KK^YaqGH0Y zdq|7Lr~B#QL<<58O?q5f;<$Q;@Lr!5_y%eFl8Ae1u8R!r;{_#(Ads(gbpJx&MBe3!}0M}rU64-5~7C1z(p_=VAd;~Jq7aXecbRAQ&Btc*yfL5B*91__VtKR)jC zmHFyv<=CVsY-Y&b$K&(jXtFsC#ip$0h(TxBes28SZ>zShu~0lBcalx8Vfwp$x2(9a z{x|b0B8QUXKWeU?=yKwV*V3`aFFE55wYjvstyX{IHjig#*SHSd7K(Z7SUvkr=$0-5 z+b?JODOCEp@pW4CZc2ojo^OH3Z`R|9PQ({Yd2HnUFAuSkurug%N?d&+nRff-6O1x=A0O*VL+vyZhX{fu5f0Hy54{LYbl$Qm3-xW0Yu%NKxA zvd9k(p3va7ncQpE2K#~RxbakTvT$DQHHXXw0WkWm)F7Cq>>9M4NT8*r$BB4 zd^WEJ!h`SgGkdY)zVltKn9i})Poj4+IdkEUZY`v`Iv3|;_k1GRdaqz}Q>oL4SCehhy-@)GuY$_)%U1x2>6m-lqjnb6ZFaVXI zPMs^Kky1`t&Ytg-_>4co^|#v(=MnXWtpG=ToL%A7@My;@vRJEzVI+Sx9p69lU;FeaOPc{vWR}jC|`bG)cJ&|z-mI1V{(EXgDq%=dt zV_wyxkWVG;@y9VJO(ebOsgc>mhJZ*2=*zCRR?lCwyxU?S^|p%!^GjCIbXNLy|9i#f zpz6Hhkh@iT5+OQ*?9OE-A)V0P(JxVG!xYMy#x+whGPU)p;91#>P4p{p>)qM2FPo=H zs<**+feNX8SEi&74T>+edF^G+k2{gKehZnBn@frZp<_$K8;&7UNX3+~;`Xt(UxEtY zz8M1f8bgGoD6VA@^GL5W2}(%q7D@?oHmbh9~&&GAC6S6x0aWmR=&AxW|EqMG_WvB_ejE(O~#a z-n#Ri!BmUqkf?2^P3Od8Ym~?G{8~MwK(C(Bg&nOdtO&fBGq0BLkNl>wNV;ue zagZo%HguT+{k78;{{!9rb5UdS5y4ifo%&U8GUxBp%2PFlDe|GJ?v3}9?otS1vd`|T zY-Of1>wS-{8SA7^hm%*P=(~_)x(N@E%89Hp2={k&5LSNvDYdF^0UW3zKh@1dGv&IV zmXZs_`9~3q{dv^iO=`_X|J$X;t8-qWd-TSx+3<#eRpaU>7!x(G{u?t0kHYb~NGQ2u z2t-WsRW6x8;R+a6GN^!onFHxRWa1+PIkwInoIyv{Ch4F^LZG`BxuyoZQWmtz1(_{b zAmb+}()Fz_yQj@?5|J)>fj8!Ud>}9 z{-Nd)q~e{4NWaKhxr!uM)1L-$7(Nd3z=a*qvFng~1UXEGn^?TK=b_e;{$(x9@ZB#dYrxT!M~QPQ8BzP3V$>Dgsshc^}D+B_)GV*21Rvva=h)?ziY^d zN5qcx9(~IqcE#4BxNWgwN%5dW@Y9{G8b^a%u;IRHxaDarV|=sn>6TwJiZ{2s8n_vtqI^@F47WvH&FE>U?H`6*VYJvuWyLO1AvJ3qze-jmK z7g(ntK>ezmv0s|{G<;f`>CMD(4CUPyUBbg{_p|ThQxKOZ-3L8MS7VuDcUh}DPrRuw zFrGn?&8#3w*H*y4CZ}HK=|TNYxA37k zNCLYSWM71p2*1~4Z1}tyth={!Mjb%>5DPoyv03qu5Gyk>^Obd*D=Qi@3?-{YlOI-x zQx<&uEks-oaX9f~a5a=N?--qy|*y$z@9zI04 zoAEnlutdg}Um6uZ9})u>9KLnqc}2kGu+v>?ttW(*(QL9(Z*@GJ1Wg&cXBx8Kg@nUa z-grj7Cj__lu#W88_FJ~Pu-h}{d1}_Fh7wVDm#tc5`YQ%24Dyq9h;7ZXPNS;xoUf7` z^LsFOPGn~0TcJi3d8JAPVcg8;iHm2-Sn2A$M@L~+JoCB1#Psm+uwwEpErR>vbK?z7 za>ID#9G~~g+im!`fO(pF84HL{KUd}LW{u~Y zDTpqFh}C0Kwhlj4Z+YSj%W4&uPir@Q?|SJE}k_NIvhKkR7N$o*5_X#W1&~^I;HY+0^0+ z7-I8+Ih)iFKhHM_&T~Hpzt~0+I}ke$q~nwAjrWhHK4)*!wX0r`-=M(hCaYtSJBg{_ zHu%~vfDD50Ho=brp!ahGYxwrBb6__7?)4B%O%B9Qn2a_^5=g~{&b2f1Wma^|kNdUN z$fV1+7+fqx9@$ES6&L`Ph%awpLFIQpH&V1r6}ZNSs6r<&EblrKHfl?wKveJrulE4} z_vR}M=@>CxE0A{0qPGiZtW=*J-$_eOupZpfW1G!^RgtEu;JflJBVbsnUAdqDpnWAp zgbY&AFC-q_lAyTVZMdOZ_nfFA3b4Pg0eTz(#G{l-$V~e0bn*Z_h@W5Hd!j%E*gFgO zv>pU0IQS%-f2^bgL{+6@Ef07$6gVh8x?conCTX|gMoa?u8uBGGBBC3DS_z<7TuOnm zJ3EVO_b5*TjzJ7HcrFcD)`QEaJ9VMm{ z6+>{e71jKF(0%*(RmlE{+u5J6F~fCrwMhPr0D;3x$%G gdtiou;Q!=buyujOhM9W(s#FIgL}Z2k2@~ diff --git a/src/themes/icons/src/famfamfam/bold.png b/src/themes/icons/src/famfamfam/bold.png deleted file mode 100644 index 1c41008a0aad561943ac2e0a51263e983776ed2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 302 zcmV+}0nz@6P)*O+k4=`T3In1@E)#Q`aZFkDMPYfMG&$edhnH{UBDv{E+`%=P?xI)~EhY1}pHd z_xtboA45TUefKVKU$1 zzuI|u0W<~v^}hcd!3wkm)c))K7cW3l;8qW`8EUl5f6e~_^=Jxg>mB~C#5QQ<|d}62BjvZR2H60wE-%s^mK6ysbEb0bG|{|z%XD{1FOrF z|NoDFVCSiCeyA_Nc4%)84-d=T1568xHr4w#zG^!-CpoxL$Ys`qU-EgzTzg!bq?FAnKAWq2a9>dfA_7w%|+_ej`8yRKX}0;`v3lC^;7>B{a5|p{pb1r^MB{tN-H^6 b<}fiVziXC0fn!P>UX(Qn(fZQHhOjBTUZ?#?!=`t{kHn*5rVoW{-l&SM&2(*20` zu8=eHiktE0oeVu?XTS+7QVR+ep;RamE(-^QpM<71L}*awN{TRv0!D7F;AXv_e>Rob%d@knl~~t8-d1vJbmrBhR|&vB$xU`Y2aK zaI_*yw}UREPPRywo%fU1ZkSt4Uz5kL%kDf6q@|_rcZ4Qh@RG6DMy?!8Zfk<8O$n|y z>Fmx8leN#z*i$ajw_3T|teXe<*V3E(wBYJ9rr@Q~^%?(cx5Wk>a?*W^l@p~A3CB5J z9wBR+4XN|bW($i>dMVTlB8ep5%{p%gkC_7G$x#!F+HU=DU zkiAypTve3YGJBQ7K=VcTYVt`dlDjYXeC(l@|C)V)zH8h0b6K0Y{C_uSWUbOTUmfE{ zqt0!qwRjZ8Ob4lg-YjV-9yl^f$|X^gYgauyA7Zneb8Y1b*T>UblH zOC=i8fBL@QgMr)9g=ps7GfduF&+u(^4BA{v?{#%_T~$No@+#7oRWfj^M!7|2*X25- zf7^Y*yL~n;oVzEN&Lf%Xc(S3G5KS@fn3YDS&f4Q8NM`YU!CT$e3>doN0=qBOa5|@z z+f@!KTm5M62!XIcR9EKXY4sS`0|qm;-b6CP?+f0@Uh$$ZN7yZ#6Y_-y!6WD&^jymq p12^&8nB8=rbrh-93vb^O{14;05j?>8F!KNa002ovPDHLkV1k^SmgxWh diff --git a/src/themes/icons/src/famfamfam/color.png b/src/themes/icons/src/famfamfam/color.png deleted file mode 100644 index 5a5d297eea8710befd2c71632758a5aa77bd5050..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa3-AeX{r~@ez?s~LstpMnUSD{< z>E`UaAFihV%g_E_zVZL6V%;-l(m<7rB|(0{3=Yq3qyahVo-U3d6^zLTm`-u0`FVIB wIOf10&hE&V%$&o+5)j0}`y%7Op##helMV@HSUlu=57ffo>FVdQ&MBb@04x49pa1{> diff --git a/src/themes/icons/src/famfamfam/copy.png b/src/themes/icons/src/famfamfam/copy.png deleted file mode 100644 index 4694909171d4375cd7c3f43eb768fad0633b34b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmV-=0)_pFP)yD$Z&-ZoG z<-c^Bb!X4JRT8AObN9s-VpqIK%$SwO=HI zfFSVv@a=m{+H$d8yh=?XxO?YLVtbR#@+O$GhoEv6|8^)?KX%Y`m#-opWZEI|H14D1~r5}AXDu&PQbOfL{J46gnEC}qSNoB z0*XQ7Ab?U>Y#IH}M{n2|4`e~E169S9FZ#V38S1y-OuEU&fg@911Mq?&B2nv_ZK7%( z6K}*3QA0dY(PUHhh7BNqHAQ$0QlhG4s?*e?2dt5Az`PGy-)7U!Dqh37;`~@{BNvzd U8?n^gE&u=k07*qoM6N<$f?Av&q5uE@ diff --git a/src/themes/icons/src/famfamfam/cut.png b/src/themes/icons/src/famfamfam/cut.png deleted file mode 100644 index 278816b8b55aafa89a3df55610f2ac09b233b79d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 593 zcmV-X0O|V^vllNdHK%t9hV=9#!ZwU%7B3O^)2V_z5TC{Ha)q2^SRT9uRZ^xkT%Vl z=s*nV+SGaZ(Z~ONo6mo{^YZI|^Rh)bM8yKHZ5%k1Bm1{?-vw&ia`w^x#3?%$5R674 zmozD(%(<(b>NZ}|$(Xk!efplW7an~0A3t&1QNiFw7Q6-sIj2bgHQr8Gb?1M`ybGUG zH^2HnbJvak4`2WIAKtlc53gmoBVGfHvgWLbTYBxUly8BZgm<2Q!rCYQXYal9f9cux z|I@d>{~x>T#(!DQv=p2Mcy;ajhk zb;0^C+y6Smd#=ZhL zV?o3c+bDCVCs0oYO{6Qo6#pP!$PMHh#|DBu&MP0#N&0l)!tkJ;JT zxdf4Zm~;h2MMao;tOp*N?Z92LZ6LdAx=r>9UcY_~Yin!R+uJME#n%V1@=-rLHrvI| zOrCQ73J`@=tGLsaW#ptq898oIN{*P7kVBt}$^MT;WbgYzvg>UD+5S48YO(aZTFiO-J#8H;y8ZE(w!BCD0B{RC`( zk}m>H!vs~`EMiMW5tuK5Q$jD=2leO}(!-Ii`{hayoIiq`76S@8zXIkISbH}I1`5>l zvPiC!P{e?SL4x#p4ZJdk;X_NW)xb9+9Jic~2}>g-W9kOIrpi`Zv511le#12gA{Z--26Abk?8 zpwMzq>N%)s8UqIki=F(m5z)0)h;Fa}0GOqnfo0k`%)2yEU`&70oKsQq`PWm8i|=J{ z%O7QPE1%|YYo6zD>t5z^8{Xz}n;*?VLY*6ao?>e3DKPfW{`Uo!$Ll|(oW#47;{bqn z$;ZFm!C3tt0rbSzyUZrTJms`FvS~@TO@J8#;7^hFG!+eBm+t{Ep8*!BBSxLiM3?{o N002ovPDHLkV1g?hISc>* diff --git a/src/themes/icons/src/famfamfam/emoticon.png b/src/themes/icons/src/famfamfam/emoticon.png deleted file mode 100644 index 87c00f2fb1f40e7d2ac1bf8373eefb541195c407..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 696 zcmV;p0!RIcP)EINP>u+qP}nwr$(CjkWC^qm8O}IomVs?&K+-0Q}ef-2>w``RKQ3wswOa zE7!=BuaYTUrpLlXn(aMLKEG_h#dY+X6k|k8f@wVg!+i^e>pJw5!%%`J!F`ruoTsVI z4;vV_sGa_*4$S23TyzX-@;t~fqaj5Mh7>s(O5%E`F&p8zTL;!-)b6VWOgX)FlLXUp z1iEb-e>@dR%m^+X2r;xLguspv{5wDl8wVwJH_{H1kaCdHe`>&b7aEZ>82Jd)Brc8} zg-dI?Knm*(F{m>xt?mfV%O-F?Z^%t%!0S5$N&9Hwrv_}6uW3IIEp;)JxG|8Uhe8VP z3o)b{Be#S1RZ}jm3)iEna6fGdId&fsc9ZX?2GSMMOyMq5pUk?4GxY&Xy$6JV4)DHi z0ndvDa6PU8=l$|<-mAzBwj*{2xj!`!FOl1DU1jv~IKQeaf-g3K5Y&mOw&vnSj9L?Z z2a4k4jLdM{DZ?P!5WS6rPYpO)8e)_);^^Ia&1%!Zn>nW^_d+T#|uv91J8&CiQdb8_J7(wtme7>=98nAK3& zp3Fwz$}dcGo}x_l6C|h!2iU-w?;>N}a6hRD=Yxt&yCfX9O0tx;@PuqZz;Y5^FQQCe z4H6GWN9XNEkfXM+Nz2*1PV9OOrd)x~b>R&d3s=B;#2jymR|~1*4@a4YqY>vD<9aa( zQp{dXWj~bo-4G&nAno2H_${TFmkX%rFBen79`cFXN%La1)3eAegwS;a*89wN3C(*k e|Hq5zzxFrJMdTot@Xika0000`J-bLY)|hn5=?99wS8vMRpZWt4P=S1@`7cLzPoqaTI*bQZ9&tzC;zQ-&(9<(3@i#SDkaap_b6`K zo%^Pl=R<(Fp=RZy|5iB{ml8C=Zv#j$m8FTM{3+ldg(J=nBpI+o~E%WrV3#xzy1h?Jzr0TYx7pDP6$!A34 zCf|Nlx%|<8ujU(p_nJ1swSia!?|ESJe|CQ`^D`6O*A9IQe7(FhfOCJ7@=(+VqC+L_hOo58)eqnWw z!}ZzI?)*>azx`j)es74J#Wp4s11vJmt&8oy^)F$#qIxt-1Q&F!b17S<7vPG|LP0Hvj-7Pp_u@3y~WD0000H5r38dL!A`u3FY@KxCGZ=Rq`UJPte!|P$_7k2HHo$S(%iZ<+KK`G09AW^>R{Or^ zyX|_3FhH^Nk)V0kvsHy#-~X@M{qa9YBS_q?_t|c{u4lW6js^Mrhk_o{UY-GI1o3S< zpY68ocuKqhU|V~Dwst}c0BN>qBf$W4TWwmO?zV0r)c~N4AdMh4NV9b#2?jtkA#4R{ zwr(KRfM$fPR`pMJTh^0k0LVrwsI8W@Km%$YV;C^-xe);V_u^YoY)#Ps0000f48F;!lhEy;n2LuHvaZO%RpeEog wusDEe*$fL|L6bx%UgmVD%aJASs7kvsL;DJ&fFl(=4nVyOp00i_>zopr0E{FVqW}N^ diff --git a/src/themes/icons/src/famfamfam/grip.png b/src/themes/icons/src/famfamfam/grip.png deleted file mode 100644 index 6a82957aec7c286253d0879c80eb2665e12a288a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f48G5=nhEy;n2LuHvaRvJ>WDz*e zvXN7(=@L(c=tEOMHO~_+Eh@`8TSOOX9tm*?vtVLS*gTe~DWM4f D)Il1Y diff --git a/src/themes/icons/src/famfamfam/horizontalrule.png b/src/themes/icons/src/famfamfam/horizontalrule.png deleted file mode 100644 index 00e180bde606c68ba19e24935b887689be6be43b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 263 zcmV+i0r>ujP)FUwnL2Nyn9$xu(p_%*@P8{?(M3Y+=ewhwj9vkGtyxScUBt1O)~0 ziod@OzzMT8NEj&ckPqVwvS8Z=E&QE$HxARt2cVrF6mmipl#`#rnz(K zW=^S`Jf(E(n8J}`@&=FatJ>ym!C#l6n|29n*d?fD`(fxaHuAu+;2ywq~b0ym_zJ)>n1feeUhood9$Q zWwZ3C>iVLCxy}jO8E(jiMp##uv0E8#_C6-0TCnJFuIqYWtZVBqsIDE zA#n2&#&6H%ss+PHO`3c<^Dgp#2q@B*qfjTHP#;90K|--nMv3VcZd?A~Qmz(Gwh;lX zOmE(?{lgvW-zK5YIM^T&sOk#n_nytViy~b)ifFPfK-%!g{U#!hko#3Y!8aD?vTnof z4>T0`MF~5i6Or`Nj@ajBL_ag&lI9i8lv;7NlDNn3aWp;)c3&e6e1e1pC$q6vrLW+o z4tp6L_T>Di!~El!4F&XHdwB_q&g5Z#zO7OAq@`g;)Jkl)F%zpUPsYT(+oU=I57)F{ zM{)vA=dQ->4^enyFGWb%7Ay?uje%P`UsD8w*JX2FA{evgG?g@9`NfGSejkeBPvM|* zO}!o=>Wx$&RWwipL40=pCH!l^w4?oT_d_CTPszI|Du5!Gw4E`zy?$_l1WuH}Do9|- zxt}m{R~K9@U4x6It3c=CgH?4K%-yHDGILMvQ@XNaw>D(>*5&ftYu#|Ybe)n+_w>Aa m4O#j)b$@tHGcG*Jxr@%t}B=AtK8Z{7YHvbS0NI#7`!LIWlS0k{`h zHoy2U!p+9;>HBYn(|5j}d3ftf+^MO0*9kcvB@A*Fzqs=1{dcCjS3d=xovDA_)6??` z%(kCDe}ZU~fPDDyp$>`{zWw~iuqsbc3+|;KKUC11jS?FmK;2mI_V)gdVk4&QDERZ| v&s0tawzjta(EC#5QQ<|d}62BjvZR2H60wE-&1_jGX#sbEb0;m;5h>saRes=ej^ zMENHE2PTT|9H0C@z%obeh(yc(@BbT)cTM1Q{C`*MLEwYW2R`r5W$*Y3f` z*2gT<|GRO2(AZFs@G)MSVL6jA`{n;q{|niscs9Rd+{*lkUB&!@g`R;T19!rI>!*7I RX9KNf@O1TaS?83{1OSa)Ql9_- diff --git a/src/themes/icons/src/famfamfam/justify.png b/src/themes/icons/src/famfamfam/justify.png deleted file mode 100644 index b6890e0aa760b0282ea2778becfacbd3b51ba200..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$h^mK6ysbEb0bG|{|z%XD{1FOrF z|NoDFVCSiCeyA_Nc4%)84^PkkPQ!%{>;v>;%$epX-fFq>zhHLY1KmZw9e@6Fhw5M1 z^W0_jgWfErJMQy4%?^J1@85DZ;RicYqgsI6Y=)n)q4K{MYC#5QQ<|d}62BjvZR2H60wE-$h^mK6ysbEb0bG|{|z%XD{1FOrF z|NoDFVCSiCeyA_Nc4%)84^PkkPQ!%{>;v?D%q89>wRi|;JH4vkaaQAl*u}h#KmWOX z-NklE&*M28677d$;w-r~i{qe*WKi_|t#KsSr&d z%?=Z>7~ntCeYfXCM>ZHAWb338pTW4}&?mU9_7h(2wx94E(*U66?@k@ow_$w8X)kxz z@B8?F;&F%pFk9{Wp6|Bn#bSV0kL&-KxuO3}EA%gd_==^E1kJmitt#C5{(s%>kN-g$ zLE?73&vx5&J;QE5)1lh`0TaFcYi6pRgo(@NKNR$s_VNr!BZzO?`E0js$5ZSE)a)z! z5296)6^|gx+4TTz?SvQr(rnX)!vN227m()j$l~a>+O$61ZQX*!0HCwK12x~o7Nxd8 z8$lXDY>;N_Ml1#ZHSbV}lVw8}hiF3B3es%d0A!N_teX+GTGc<@ZCOvE0U#T#ptf4p h0u88r3}g=$0095L&^C8NUdR9d002ovPDHLkV1fjXz5f6J diff --git a/src/themes/icons/src/famfamfam/maximize.png b/src/themes/icons/src/famfamfam/maximize.png deleted file mode 100644 index f04635698cd550da5787a4d134af38bded052bbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 536 zcmV+z0_XjSP)tfp*NeYS0uZQHhO+xB+u%RjH3?orQr5a*ox0~NTkfE@lyGkg~&c+ZRg zK>hA8Z7N_`mqWKIg=R?t)q)7Dpzg5*%}^?Qnu46s^0Mmw5Idb;A$l7s3F)IK? zl4~D|G4(l!`uj5YPpxnq>NoQQl2fSes4q*FYIC(=QANZBU_+IggB;o;|QSa;MMfqGGl*2{V{ zoK-A^E|K#y>5SY9tAOGt3R|I-y z$7D@p(#m;eShE7o5Hkjoklvq&)Sh@Gcf}#GBL=L1g_k9?VOfFNlXBFZRFX+^1ZjPV zDBR3J&RT$l&B|6tZ=TFA(_a4U?i31 z4JC5~3GGbTtx%x9p)Ycj%kcQ6q6iT7lw%1 aQ2Yl(NUbTw5_!o00000NklB8O-&6o5Zl&2|KGUg>HnHl zPX{Ov%a=X=U%K@1|Ki1u$#(%rvvuAj@?!y{8Rh~bBcp6>ZSDUmDk}fw07*qoM6N<$fvui;^1fjI}HND-j{6T<+bZ|7Z2 zNio(%nv(1$OpMG758r%e=#7$LB*yvhFmSBAt|=+Uv6h>IcG9Qzg_b>kkX2t`RoeJ@;chz@Kpc+002ovPDHLkV1nEZnpyw= diff --git a/src/themes/icons/src/famfamfam/paste.png b/src/themes/icons/src/famfamfam/paste.png deleted file mode 100644 index d3dccf9faadee0644dad3d35c37b6f90ee480f40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 582 zcmV-M0=fN(P)-GQUYP0#PWb zsELLMwjKdgf3{YoFzI-&_+|GgW=cT1tYJ`DQH1E9aupXdku#eUFU=!@)|V_|r^0+*>) zQIuMdf}cBJc(oAv=kuU_G7Fl=Gw}QTSiCqe6wisLJNx3_2s@vo6Y*%0Sylw=8K?$$diwhSnoUM?s!1{F)x2k?Hg#|gc#&N46 z;PH6ia5zw0T#UTDJpSf(yK&{p6_&8T@_9W}_a}2W`{o#AT_1xd+k02E$bqu5GUVsy zOT7`pVS)MM8t!(^4GLcwg^Wuh@n~~TE(!z!EOEJ9EGaB3+ zhk?V#2O;U`K-^o|DPjfue!r0L#L9x_OOSes!$>~dABhM1;qI~y5d!K3O9)BuPxVl2 zpoP#pT0l!V52}0f#Kw_=HIM|uh*SaV?lJpP#h#^AM==&@3c;FXiqf!50bFQ UKGdiNe*gdg07*qoM6N<$f^p;))&Kwi diff --git a/src/themes/icons/src/famfamfam/pastetext.png b/src/themes/icons/src/famfamfam/pastetext.png deleted file mode 100644 index 595c16a8ef6efffb97164149fbf8fed9f9b91166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 579 zcmV-J0=)f+P) zkprw8Q5Z(g?AEs3sJ7dvacbLcoZ2?xGOEp>wr#sXZSBmx|Ly+C&OX1Be7mFXTzSqp zlr_Vu)&%a8k?$kdzbr!L;H@57r6Dj2XkVaMY5Gi=$?s2BQ1X{(%Ep3&dB9XGy^}5^PeFr-L83dK{7AS=O^8-c< zFSoDMCgAwwuH$h0`|y@LCCcXlG^7`RSe!9Lij+aD!8su{-oHQi-~XUwDsUo*F-Q>8 zfOBL|27y6rkQ`Z@$Gy*m_-CWw)aP(sF5c&?$=I=Dmxu_~TFv8xz#=99t0IeUB1H3+ zpy#l;_`Xj%#;Y(IjRs@Jj9HQtU;>;KoDsyjc!XFi#)S(P&_YOf-J(Scj4>nyS`eer zYfq<#(y(DefD95%DuEz@)zRZoK?F$@u3x{NEQkN$40I3`Bt}<(AmI|QTF7(;A;}q_ zg+OpN9u-*+@eInfYu8AR%38K;nViAd!1vqaFIN#KE*>FA0MV}nan8}GQKJmy@IMqR zI(_0qL7+Yf^zqLkjmeWI51!|d33`kwz{_lH0|yR_SZl|}Q#>A0M?_NR*?&cPWNTNA Rq0#^V002ovPDHLkV1iHE1(E;& diff --git a/src/themes/icons/src/famfamfam/print.png b/src/themes/icons/src/famfamfam/print.png deleted file mode 100644 index 9584a17f4800e2f561915ec7b69352bdadcf3bda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 664 zcmV;J0%!e+P)ddeEoi+o&IVQP70k+lL z9{U=uo&ft=uEM^Cr?9DH>EB6Xw$R))t~^+lG1Yrw1rDT2>`N%v6Du*fAx7@cD+q3! zk-s1P>$7(XY%1CEW0?w~RV_gS?ve__b4n;RI*2y3DEWN_MwtVj-zl)JWGf7Ue~IAV zH7)qdYB1+jSlpJv(6jAB8BFtrHMa^13k#pOu4Ji>q$-S()BR^c%03ZTm2xmLGJ=$p6quWvn;Ha9 z$PZgvTgc7LeGD|qWHRCA<~C;#sI*!w3a#>Vj1Uw_@o=;$bli;K_mZ@lpa7-Ssy?YG}3t*xyfb3)0?%tTyV9POr) zlM{@MjbUVDMBkm|Uw-*zFruQObYFb&h2aG){QBD;&^O4sl`p^k4sX5n7R`2dcjLtu zUj!pKIJnc-*Y}BshX(>%Igl$<*gIBXm#}@L#Kyh?%R5pmY>6RPsu9@2!Amc_WGMch ykaguO1h#T@p&fjLwqFoJ;ZevpBH-#S*E|Kg5(LPc)Kr210000`*APsZg=K9+1+#2O#pm} z?+f@uHP|vmjDf)`G%>Ev1uDy0CZXvHuT4$IoJ6J=Gx2U@8%9?|*gqv~91>O!2+Mnf zg&NLCoHi%zeAY0mdDl=Mpmx^G37lH@P0P1 z!t&zowY)``+_;j5Ssqw^IdFRla`V`!; pW`J-bLY)|hn5=?99wS8vMRpZWt4P=S1@`7cLzPoqaTI*bQZ9&tzC;zQ-&(9<(3@i#SDkaap_b6`K zo%^Pl=R<(Fp=RZy|5iB{ml8C=Zv#j$m8FTM{3+ldg(J=nBpI+o~E%WrV3#xzy1h?Jzr0TYx7pDP6$!A34 zCf|Nlx%|<8ujU(rG~znZ6=K?$t3nCz?POKkps-`e~C-?bh8zpg0ye>z+D&n{<{T(AQDm{VN9=y54s z^6-B|&#gB)LC0)inpIr)3$J$(eD@8g`Tr!}|NqMc|Nn1O{QtVk;r~t-=6jG(&p5X( zw*S_@gbBC*2Q*)Qs~vEpSJ`Q=fRg*7|36UEk1~e;?|}GW2J?TQ_!FWGI2p_p@@v|F0@p|KCkv{J+C#5QQ<|d}62BjvZR2H60wE-%M^K@|xsbEb0bG|{|z%XD{1FOrF z|NoDFVCSiCeyA_Nc4%)84-d=T15F8Pf7@TU9WZv8J>i#po-x-R*G1BI{vZD8bhg@W z3+Fw7y&Qi7e#~?+&-nYF_xfLUrbe{@x!DZD9zOCH3%*7IZDR0r^>bP0l+XkKWQ0i? diff --git a/src/themes/icons/src/famfamfam/rtl.png b/src/themes/icons/src/famfamfam/rtl.png deleted file mode 100644 index 4b30d93888a2a2df0ac301357ded7aaa78114f60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 386 zcmV-|0e$|7P)XZ+Og_?JObs^OR8zr zEiG~Q4d#Ilh(Y|`ruG)tRNVqDc*nik33}8xLqgan#$Qm~+8#DBh@Y)1Z-I5i4Pe5H z7|fYY6D^=uYf!b4DL}AQ8AE`Uz2?{G0gL8y#R+(;R;4$1)>GToT^3s4KPOsAfFSk!0~v78HWWf<+5i9m07*qoM6N<$g3K1GZvX%Q diff --git a/src/themes/icons/src/famfamfam/size.png b/src/themes/icons/src/famfamfam/size.png deleted file mode 100644 index f5767600b141151cf85384e6195c98744d129b78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmV-H0>1r;P)-T0Q%2O>yqL+3(PDV}fJLjagR3m%EIT z&hY9*pJap^@K;3S(m!|i|9_Q~F2Tg?ny&}vEPr%w;+~iP`*%J6-@X0$|H37Yemm7& z+om6LnhV1ff32+kBlE3mugQc>ySuA+<>ODqD;|C=T=MX{UHRo12JxpkuzCaN1r!5p zDzB6mEPM3bz2nwe=elbPn$|t}Z?KW?f)*YPh~CYySQ3CTVBW^kYwQ87H3Us9g5&zf0BCOX^;S z*svQQAn*)Cn`NDk$(VcpTTu6{i-z&1{q!P_Yni8?T~GxyAh_+uCsnuoyx0xk;CN<~ zd`2{G^6giZ%OCysYQAyVD(n0v%ZzhdU8}C%Xk795e^}eipURH=q_G>o$M@g9b&(|$!@n2hGzYkQ(S+!xc-+edH6q~=hhpYpkuZ$IThFa z!s;G}>$9ib`Jd2#`@f?7-Viy9ZA>Tz?BkL61WZi-?@Flr4`{yrRy*KGud>r#0VVrA zTH3yc7daJPcokT8?Z0o$)&GW}$M(uvZZkwNU?Ky9<^@K^)0=@b!;k|2__Xl6U-E_~ P00000NkvXXu0mjfd$%v3 diff --git a/src/themes/icons/src/famfamfam/source.png b/src/themes/icons/src/famfamfam/source.png deleted file mode 100644 index 8b70fd9bf3fe884cd2c4d1495be0799140f3d0aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmV-M0lEH(P)!BPchUl`5k$B`xerdSIWKC#5QQ<|d}62BjvZR2H60wE-%c>*?YcQo)$~!=E82)Uh++;F&jD zu6$~lIdS(!trOMLL-`gdpJM)>95`Y2v~Tu1nGbzCkmj_@`_TUv{}qjEd;c5X*qyLd zsi^$L{{#Q!{^y>bu~17xU-v(M^T+?W|GX7;N}pt@cjU;OvaI&{i~V;bd9?3bdUHB4 zXXgK;azl|D%Vz$+-abp|Q{R3W=SI(2@2s~Pe|kD8^U%{hvR8V!nFJW3t^U|YbADb9 PbSQ(TtDnm{r-UW|^7(Nt diff --git a/src/themes/icons/src/famfamfam/subscript.png b/src/themes/icons/src/famfamfam/subscript.png deleted file mode 100644 index cc4b576d52a3cf45175110bd38779c61392c2040..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 367 zcmV-#0g(QQP)@w6wGX@$vBr;o;#2{QUe5xVpL?AZP$ka{y5Dhm@3* z|3J+XKw?164M5EcY;0^4i1Gr^W(T0=|B;cA|ACqdKsJ*c20&*|2n-DT@8;(AA84}x z$p!#z7655>adG)?WMnjfWCK9X2HIR;ZEgMEz`)?Yf`WnrNIYc91BKF6&o8uWe)++- z>uv)~J&MiH04o6TH8nLS0A283LPFw$prD{Z^1R0zfEpFN+HN&8tbhI=rVrib10ZJu zH5&kJJ^<8w0I2x@7Z=w778Vu*kh;WK4=<$5d-Q;;gk)cFts!jEy$j|!mkdZYz`E#4 zfK&Cg1tu961PqfeIOxTnRUpX#@79|K(&s+>pFHcq|FDU7KMbDC1OSf^p<@n}q-X diff --git a/src/themes/icons/src/famfamfam/superscript.png b/src/themes/icons/src/famfamfam/superscript.png deleted file mode 100644 index a8424ebb95923ceff3d5c782e0098c3d93fbfafb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmV-!0g?WRP)8j@!S~kD@;M;Y#fn)=c=RMv4)TrRqcB`Rb{qz51dm(Yw!wV_% z9zDP?puD{NKyh*Lf!y5O18He#2jb)76~e>A5BT}{9dLDZJpfW;UvaG=Y|_08<~f%P zFbn`{4ghNYkdl(}AEpFHcq|FDU7Ki~`lptC0g1_u6jb94I-v{``U zXaw3U0MhK@;_~0f$Y=t|27sImw7J0A+WNnNfx&+T1qBBJ1|V#P23P@zuc@gy0qBDN z5)u+01O){R@Ed@z`2fh-K+Og~n-2gr9{_4Tz{SONfQ5y{U~pz805*)FV;~X3KL7v# M07*qoM6N<$g8!wQo&W#< diff --git a/src/themes/icons/src/famfamfam/table.png b/src/themes/icons/src/famfamfam/table.png deleted file mode 100644 index 9011d106764ccec0615fd9a632710568551c00cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 582 zcmV-M0=fN(P)97Z8lDWT2aFWwQbwB-Lq}mwr$(K-8tL;&V6a7_M1HWe*EpsXaN5e@#C7( z_rfK)uhlWB2m1sGn>Y!J7!{_Gofw68pcm4HR$vS7{F->>UC(p(I-a=JS$x0yrdgi$(WxJDf|curD&hs=x@-TwM&ZHPOy^!@JZMyh?t;vxEoY>`mJ; z6u>rK5{rLW;_Ma6VidqCMkN+KQdNHvarT^P0SaIi*{J{k-f3NYS$>&c&!vGeP8#N- z0ES`h4319XlcB$7)wCA<&X~N3PDe8#9F!l-u4VSU{>O4IGyzr_QKunQD>^F%omN=!o zncz|*f-6h_(2F~dVcf+zU`zl{+^Xr7frJtXfW*?TpJ3b5RYa88eYF-+Vm=2Tfcwss z^bC%p?jNJ0XOtH8Fb$nU)V2*!)zZ(JTl3M4IfG`*DF8I1PksFacN{9xZdjKNU$Q9X ztVsbU401WDlg$CmO!mA>W!=N8?A2R{e#|-X&vF-YMi zVQj+p=4beqsw5)0=)Kc&g*+v;`qaV zJjr?YbIv{IdvET&tsn-&e2>S+`^12kp;f9*T!qeY_<0iD)Sh6B9Bl)-0o{oHw8~WX z6xO%nSSg@vy%=;0-g+S-?!y$rd5+aar9%NP9}NY>eRbuvKEV?Tgd%*cGSo+ePB(99 zuqd_$G^$f|*xI>9t2WO+8mP4=8g_fcE`e{<*23hWwUTPCet(xJ@nV<9?~PJ_$mffC zr3V|N?tiC>nTK2H9E^fH7<8*A!ZuhMnwqR++qPMnt(N9SOB2nh#(lz={%G z?Minf5<0jyA_{(~A>1WUnT|eabTf2AfNoNmddgJBfjv{gr}fCR*P$8Z~yPMk`{&-9RZ=9iyt{BZ5+{8yRyOi~1x{qg$u-+uG;+?TWQ z>9_|#t&a7_;v*gs4~rg>^So6Q-|3*pVIy(>ir4+-8@pfL>2SWbg~a_AKK$VHIPP@F z+3VU2;63;L$@dZ??;JhiJm53~sMWTutvoHGs&4Zk~qt!jjV#@SAWGjehl=C zgTiQHLf0c{G0Q>j=Rw6;>- z(U&B)6Pug6kF@u|MAZU?chYjH_hBgAuCjSH5tu$rZ4pu8{ zf@-*Tc;btxNp7-`BI!$)=VnhpDoH$b<;qM75((n*>C8+L#zu+vAOAc(2BXJm`Ox?% z497?@J`AyA1Q-qt5*!;Szf;R=kk(nsgNV(zi!>W zm4lqZOSctXqKSzvr@$T_C}%3=0HzF;swCP&1E!o3uL1KR*w8 tD5UW}r|=s-^m}QRra=FI3h9#cYSkqGrNqSURLv_?#<;XhUH=I-vHLX%T@e5P diff --git a/src/themes/icons/src/famfamfam/text_rtl.xcf b/src/themes/icons/src/famfamfam/text_rtl.xcf deleted file mode 100644 index 8803d43fcb378f165dbc2da2041be88eb1466d63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1884 zcmchXZD?Cn7{|{|YMQ>xt@!du@n-Fy6}uN?NS7sTs$olHOqq%wrjp*>Bp1^pP41+F zb!}%`(>1M0bY&Y(?Z%Kz82CX}4D>@g%&Nudd{_LSqbWh8wEIxD-Q@9kZqJ=9cHq8v z;JN2_{^vRWb92s<8&KM#VyEO6{Ypq?*f#JWuE7uld^~_*ZA~#of$c$zGK_MJhdEQ; zLzw>v_8S6d+o-hr0&-&@rW`}=Gay+0sDLXntQuXl~HK$}n8 zx_PVK)_`q%ssWd_t+CXY7w-+(mC)Z3^8WDxIC~7aM3t?I?KwZLrSzQ;*060XF-Kd95Ae$DXW4r zc8pG*a;Q~e7+kf2t5@*46}%pqe94a*-K??Rxb6G&8U0~$a5ml;b4|~$)=WMcw?a{@ zgKE&~8n!?sT&weV-S$?`-k0{b1=|7YyobGggCp;pI6ZdmdR>3P4FuCUalRT)p<)4?q2qBlFJFNuE8G%aM5^P3Gy7%jS>T$lSK+aWc0( z<8Iz=ckSA<@8wr~05mcR&7;(NpiAITs}JEibxxwj2zS zx!pzPu3co#ik5L!&5A!Su_~rr1;8sSUB+cqtTc^XHPgO95i@>WqNgRxJanGMfz#!$ zQ{_(ewU`>(91RC((nJqz|4X$1Kyi7yHLJzU=dde#owM=sSS@AUtF^MXX8*>^xw6KsT9xP5r+v++y9rBa5hFI=9UIu4mM@%WW1lNm^* zh({-KlW7 zr1WUe)unH*UH@}o-ZWn-kn>-QHx>&}(0Trb&U2&}7KrC`{v$uXFbDZO?f!cq5BXU# z%xf@9a0`bz2(w(d3tXq&S@FpkFhePe)l>QnEAV!fWocl(L#6Brd8y_CfSzJyH*02e zs$fD^qgD3=8|mha(pbMw4#|?LM8e`8UtBL7<2z(jHC4`k`3ByPd9;@PDrCkj#=x_Pv|(E z(9Edajo#_Q1?)O_i1^GLb{sf_prV>qqnpjws?jK`iQF^Q{xhKX_6ox>yp5>N%C#MWfPy#qP#p zbF=957v!{FB&Xvt0B1$ZxFA{)0yuuYNVg9y+L?HA8XZ;Fk=E34JgSQAm&@65v5c?x zyg*^wU4H%KwpZNT{lCEt2R()gZH};S$T>pY;%Gt*`Cs-QV9JZnO=YQ~TB-ng1DCVH> dlRX*A2LN(3{YL4I3;F;6002ovPDHLkV1mjIcB}vZ diff --git a/src/themes/icons/src/famfamfam/underline.png b/src/themes/icons/src/famfamfam/underline.png deleted file mode 100644 index f95a905e0aed1ef804c63804f82e7d00653276d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$x;OXKRQo)$~!=FKD^#YrPe`$0YnzY{&Uz8H$Syy15VTF|!g!2bKc_a`&7tbL?#y?@~W--G}59<6k4{m*lX&*=G4 zkqs?NW;Xq+>HXXFd+Bdi9uKZ8jVu4we~N#%|4048|2F?`{x?1>>r;V<1vlO}RMGo?dIxq@bW{fK`c<3qbv65{^%jf5 zRoPtr^;a%+wCI-~!K!rCFX8Yt#-dj~7<)HXXfIMlVawvwASZxWiONl#A?DJ?B!0OaTA z_pYq0yoBH1-%r4SM-Mrrs;cUgo}T`2VPWCEkB`q$dwcu0k&%(4t*tEyKyq?2frgKq z%jI4IkKUI%s4FWgd(qzB9?gP}jg5`Bo;h=7>*VC*Rsg-dy<0^h(N@-%V)Luuz@vwp zQdCrojgF3f(ACwI;pXOc!qn9CwUw0>admYi0NA}UG<@XXz@vwpl4U1HN5`ec#>NMH zKL4IrEGFIE-6So@e$$=*Dk%I$|9&$=bN@@dpdn$Hzb{8TdBA&*_$G>3LSKi*< zK>$L+6PH;17(Q}v;L-c;e_)%x++&h7FI4g#-{w-j%E)_+`Tg=(FiTkwg|;!T6urh} z)qJN~WIe{zTuN51O1ln6{qzKS(KGvlTbVZsp5t23o>i+4+2S5)mtko&--!c~PD301 b`DpwA{kwbC54?PM00000NkvXXu0mjf5XmU= diff --git a/src/themes/icons/src/famfamfam/url.png b/src/themes/icons/src/famfamfam/url.png deleted file mode 100644 index db1504bb2f8bc7e39a418057291772f25ee62c88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 512 zcmV+b0{{JqP)K|27rI^{|TV4 zufI4tIy$Yatn5R7e?M|_b05dX#%c&(D(d^3aYqfcG5}>|<$1QYw$)8dO?dU{74F}^ zkJG15qo}CpK~7H2ncKH-k8pPG+&NG~EpMg)N=i!hDJdzRu3x|Y!PC?8fQ^mKL|9lD znwy)Em6Zk7oN>2l)27GN@<#dv)y2id!!0c>5e^Oxiwq15z8*h*92YKJz?m~=uzmY> zaK;@q)beH;ASWjm6%i5fvAw-L)!Etku#u6`n7O$*oSd9MXU!RR)KJTtX~0@xc6N3* z>+0%0ZrQTs{f-?w(9zL>q@*NdW@dtQ!%!KL+I*+N>mA@(Y&2;aC)YF$ShZ@^Z1F@z zYisL=p`oGQVq#*3g^zl8c=!u9iOTaIE!rA{eb?G>>BSK=9F2xYgB&zsmeu~&xAvbpcT7fxaLSODvkt#R&hA+ z&t4#er7pE=P;M1%flQaQHEEqE(mGGp zd-2RI5MFfj@y|gqkxd(1Vi?W&VPOomc;#Aq_ z5&J7Ea3%MYSs{-VDjO!R3CQ;G_ifA4Dd^qPAXYtVdqPOhiK!{Cx>6#IP!5@iJMd#erfbL-MboFyt I=akR{0JpA_umAu6 diff --git a/src/themes/inc/defaultbase.less b/src/themes/inc/defaultbase.less deleted file mode 100644 index 3ce6d11b2..000000000 --- a/src/themes/inc/defaultbase.less +++ /dev/null @@ -1,448 +0,0 @@ -/** - * SCEditor - * http://www.sceditor.com/ - * - * Copyright (C) 2017, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - */ - -@import "elements.less"; - -.sceditor-container { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - position: relative; - background: #fff; - border: 1px solid #d9d9d9; - font-size: 13px; - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - color: #333; - line-height: 1; - font-weight: bold; - height: 250px; - - .rounded(4px); - - *, *:before, *:after { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - } -} - -.sceditor-container, -.sceditor-container div, -div.sceditor-dropdown, -div.sceditor-dropdown div { - padding: 0; - margin: 0; - z-index: 3; -} - .sceditor-container iframe, - .sceditor-container textarea { - display: block; - -ms-flex: 1 1 0%; - flex: 1 1 0%; - line-height: 1.25; - border: 0; - outline: none; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 14px; - color: #111; - padding: 0; - margin: 5px; - resize: none; - background: #fff; - height: auto !important; - width: auto !important; - // Needed for IE - width: ~"calc(100% - 10px) !important"; - // Allow iframes to shrink - min-height: 1px; - } - - .sceditor-container textarea { - margin: 7px 5px; - } - - div.sceditor-dnd-cover { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: rgba(255,255,255, 0.2); - border: 5px dashed #aaa; - z-index: 200; - font-size: 2em; - text-align: center; - color: #aaa; - - } - div.sceditor-dnd-cover p { - position: relative; - top: 45%; - pointer-events: none; - } - - - div.sceditor-resize-cover { - position: absolute; - top: 0; - left: 0; - background: #000; - width: 100%; - height: 100%; - z-index: 10; - opacity: 0.3; - } - - div.sceditor-grip { - overflow: hidden; - width: 10px; - height: 10px; - cursor: pointer; - position: absolute; - bottom: 0; - right: 0; - z-index: 3; - line-height: 0; - } - - div.sceditor-grip.has-icon { - background-image: none; - } - - .sceditor-maximize { - position: fixed; - top: 0; - left: 0; - height: 100% !important; - width: 100% !important; - .rounded(0); - z-index: 2000; - } - - // Used to hide scrollbars when maximized - html.sceditor-maximize, - body.sceditor-maximize { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - overflow: hidden; - } - - .sceditor-maximize div.sceditor-grip { - display: none; - } - - - .sceditor-maximize div.sceditor-toolbar { - .rounded(0); - } - - - /** - * Dropdown styleing - */ - div.sceditor-dropdown { - position: absolute; - border: 1px solid #ccc; - background: #fff; - z-index: 4000; - padding: 10px; - font-weight: normal; - font-size: 15px; - - *, *:before, *:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - - .rounded(2px); - .box-shadow(1px 2px 4px rgba(0,0,0,0.2)); - } - - div.sceditor-dropdown a, - div.sceditor-dropdown a:link { - color: #333; - } - - div.sceditor-dropdown form { - margin: 0; - } - - div.sceditor-dropdown label { - display:block; - font-weight: bold; - color: #3c3c3c; - padding: 4px 0; - } - - div.sceditor-dropdown input, - div.sceditor-dropdown textarea { - font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; - outline: 0; - padding: 4px; - border: 1px solid #ccc; - border-top-color: #888; - margin: 0 0 .75em; - - .rounded(1px); - } - - div.sceditor-dropdown textarea { - padding: 6px; - } - - div.sceditor-dropdown input:focus, - div.sceditor-dropdown textarea:focus { - border-color: #aaa; - border-top-color: #666; - .box-shadow(inset 0 1px 5px rgba(0,0,0,0.1)); - } - - div.sceditor-dropdown .button { - font-weight: bold; - color: #444; - padding: 6px 12px; - background: #ececec; - border: solid 1px #ccc; - .rounded(2px); - cursor: pointer; - margin: .3em 0 0; - } - - div.sceditor-dropdown .button:hover { - background: #f3f3f3; - .box-shadow(0 1px 1px rgba(0,0,0,0.15)); - } - - div.sceditor-font-picker, - div.sceditor-fontsize-picker, - div.sceditor-format { - padding: 6px 0; - } - - div.sceditor-color-picker { - padding: 4px; - } - - div.sceditor-emoticons, - div.sceditor-more-emoticons { - padding: 0; - } - - .sceditor-pastetext textarea { - border: 1px solid #bbb; - width: 20em; - } - - .sceditor-emoticons img, - .sceditor-more-emoticons img { - padding: 0; - cursor: pointer; - margin: 2px; - } - - .sceditor-emojis span { - padding: 0; - cursor: pointer; - margin: 2px; - } - - .sceditor-emojis > div > div:not(:last-child) { - margin-bottom: 6px; - } - - .sceditor-more { - border-top: 1px solid #bbb; - display: block; - text-align: center; - cursor: pointer; - font-weight: bold; - padding: 6px 0; - } - - .sceditor-dropdown a:hover { - background: #eee; - } - - .sceditor-fontsize-option, - .sceditor-font-option, - .sceditor-format a { - display: block; - padding: 7px 10px; - cursor: pointer; - text-decoration: none; - color: #222; - } - - .sceditor-fontsize-option { - padding: 7px 13px; - } - - .sceditor-color-column { - float: left; - } - - .sceditor-color-option { - display: block; - border: 2px solid #fff; - height: 18px; - width: 18px; - overflow: hidden; - } - - .sceditor-color-option:hover { - border: 1px solid #aaa; - } - - - /** - * Toolbar styleing - */ - div.sceditor-toolbar { - flex-shrink: 0; - overflow: hidden; - padding: 3px 5px 2px; - background: #f7f7f7; - border-bottom: 1px solid #c0c0c0; - line-height: 0; - text-align: left; - - user-select: none; - - .rounded(3px 3px 0 0); - } - - div.sceditor-group { - display: inline-block; - background: #ddd; - margin: 1px 5px 1px 0; - padding: 1px; - border-bottom: 1px solid #aaa; - - .rounded(3px); - - } - - .sceditor-button { - float: left; - cursor: pointer; - padding: 3px 5px; - width: 16px; - height: 20px; - .rounded(3px); - } - - .sceditor-button:hover, - .sceditor-button:active, - .sceditor-button.active { - background: #fff; - .box-shadow(~"inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2)"); - } - - .sceditor-button:active { - background: #fff; - .box-shadow(~"inset 1px 1px 0 rgba(0,0,0,0.3), inset -1px 0 rgba(0,0,0,0.3), inset 0 -1px 0 rgba(0,0,0,0.2), inset 0 0 8px rgba(0,0,0,0.3)"); - } - - .sceditor-button.disabled:hover { - background: inherit; - cursor: default; - .box-shadow(none); - } - - .sceditor-button, .sceditor-button div { - display: block; - } - - .sceditor-button svg { - display: inline-block; - height: 16px; - width: 16px; - margin: 2px 0; - fill: #111; - text-decoration: none; - pointer-events: none; - // IE & Edge inherit line height so reset it - line-height: 1; - } - - .sceditor-button.disabled svg { - fill: #888; - } - - .sceditor-button div { - display: inline-block; - margin: 2px 0; - padding: 0; - overflow: hidden; - line-height: 0; - font-size: 0; - color: transparent; - } - - .sceditor-button.has-icon div { - display: none; - } - - .sceditor-button.disabled div { - opacity: 0.3; - } - - .text .sceditor-button, - .text .sceditor-button div, - .sceditor-button.text, - .sceditor-button.text div, - .text-icon .sceditor-button, - .text-icon .sceditor-button div, - .sceditor-button.text-icon, - .sceditor-button.text-icon div { - display: inline-block; - width: auto; - line-height: 16px; - font-size: 1em; - color: inherit; - text-indent: 0; - } - - .text-icon .sceditor-button.has-icon div, - .sceditor-button.has-icon div, - .text .sceditor-button div, - .sceditor-button.text div { - padding: 0 2px; - background: none; - } - - .text .sceditor-button svg, - .sceditor-button.text svg { - display: none; - } - - .text-icon .sceditor-button div, - .sceditor-button.text-icon div { - padding: 0 2px 0 20px; - } - -.rtl { - div.sceditor-toolbar { - text-align: right; - } - - .sceditor-button { - float: right; - } - - div.sceditor-grip { - right: auto; - left: 0; - } -} diff --git a/src/themes/inc/elements.less b/src/themes/inc/elements.less deleted file mode 100644 index c26cac272..000000000 --- a/src/themes/inc/elements.less +++ /dev/null @@ -1,98 +0,0 @@ -/*--------------------------------------------------- - LESS Elements 0.7 - --------------------------------------------------- - A set of useful LESS mixins - More info at: http://lesselements.com - ---------------------------------------------------*/ - -.gradient(@color: #F5F5F5, @start: #EEE, @stop: #FFF) { - background: @color; - background: -webkit-gradient(linear, - left bottom, - left top, - color-stop(0, @start), - color-stop(1, @stop)); - background: -ms-linear-gradient(bottom, - @start, - @stop); - background: -moz-linear-gradient(center bottom, - @start 0%, - @stop 100%); - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",@stop,@start)); -} -.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) { - background: @color; - background: -webkit-gradient(linear, - left bottom, - left top, - color-stop(0, rgb(@start,@start,@start)), - color-stop(1, rgb(@stop,@stop,@stop))); - background: -ms-linear-gradient(bottom, - rgb(@start,@start,@start) 0%, - rgb(@stop,@stop,@stop) 100%); - background: -moz-linear-gradient(center bottom, - rgb(@start,@start,@start) 0%, - rgb(@stop,@stop,@stop) 100%); - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",rgb(@stop,@stop,@stop),rgb(@start,@start,@start))); -} -.bordered(@top-color: #EEE, @right-color: #EEE, @bottom-color: #EEE, @left-color: #EEE) { - border-top: solid 1px @top-color; - border-left: solid 1px @left-color; - border-right: solid 1px @right-color; - border-bottom: solid 1px @bottom-color; -} -.drop-shadow(@x-axis: 0, @y-axis: 1px, @blur: 2px, @alpha: 0.1) { - box-shadow: @x-axis @y-axis @blur rgba(0, 0, 0, @alpha); -} -.rounded(@radius: 2px) { - border-radius: @radius; - background-clip: padding-box; -} -.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) { - border-top-right-radius: @topright; - border-bottom-right-radius: @bottomright; - border-bottom-left-radius: @bottomleft; - border-top-left-radius: @topleft; - -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; -} -.opacity(@opacity: 0.5) { - opacity: @opacity; - @opperc: @opacity * 100; - -ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(opacity=@{opperc})"; - filter: ~"alpha(opacity=@{opperc})"; -} -.transition-duration(@duration: 0.2s) { - transition-duration: @duration; -} -.rotation(@deg:5deg){ - transform: rotate(@deg); -} -.scale(@ratio:1.5){ - transform:scale(@ratio); -} -.transition(@duration:0.2s, @ease:ease-out) { - transition: all @duration @ease; -} -.inner-shadow(@horizontal:0, @vertical:1px, @blur:2px, @alpha: 0.4) { - box-shadow: inset @horizontal @vertical @blur rgba(0, 0, 0, @alpha); -} -.box-shadow(@arguments) { - box-shadow: @arguments; -} -.box-sizing(@sizing: border-box) { - box-sizing: @sizing; -} -.user-select(@argument: none) { - user-select: @argument; -} -.columns(@colwidth: 250px, @colcount: 0, @colgap: 50px, @columnRuleColor: #EEE, @columnRuleStyle: solid, @columnRuleWidth: 1px) { - column-width: @colwidth; - column-count: @colcount; - column-gap: @colgap; - column-rule-color: @columnRuleColor; - column-rule-style: @columnRuleStyle; - column-rule-width: @columnRuleWidth; -} -.translate(@x:0, @y:0) { - transform: translate(@x, @y); -} diff --git a/src/themes/modern.less b/src/themes/modern.less deleted file mode 100644 index c590117e4..000000000 --- a/src/themes/modern.less +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Modern theme - * - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ - -@import "default.less"; - -.sceditor-container { border: 1px solid #999; } - -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; - background: #2e3436; - color: #fff; - margin: 0; - padding: 5px; -} - -div.sceditor-toolbar { - background: #ccc; - background: linear-gradient(to bottom, #cccccc 0%,#b2b2b2 100%); -} - - div.sceditor-group { - display: inline; - background: transparent; - margin: 0; - padding: 0; - border: 0; - } - .sceditor-button { - padding: 4px; - margin: 2px 1px 2px 3px; - height: 16px; - .rounded(12px); - } - .sceditor-button:hover, - .sceditor-button.active, - .sceditor-button.active:hover { - .box-shadow(none); - } - .sceditor-button:hover { - background: #fff; - background: rgba(255,255,255,0.75); - margin: 1px 0 1px 2px; - border: 1px solid #eee; - } - .sceditor-button.disabled:hover { - margin: 2px 1px 2px 3px; - border: 0; - } - .sceditor-button.active { - background: #b1b1b1; - background: rgba(0,0,0,0.1); - margin: 1px 0 1px 2px; - border: 1px solid #999; - } - .sceditor-button.active:hover { - background: #fff; - background: rgba(255,255,255,0.25); - } - .sceditor-button:active, .sceditor-button.active:active { - margin: 1px 0 1px 2px; - border: 1px solid #999; - .box-shadow(inset 0 0 4px rgba(0,0,0,0.5)); - } - .sceditor-button div, - .sceditor-button svg { - margin: 0; - } \ No newline at end of file diff --git a/src/themes/office-toolbar.less b/src/themes/office-toolbar.less deleted file mode 100644 index ef329f07b..000000000 --- a/src/themes/office-toolbar.less +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ - -@import "default.less"; - -.sceditor-container { - border: 1px solid #8db2e3; -} - -.sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; -} - -div.sceditor-toolbar { - border-bottom: 1px solid #95a9c3; - background: #dee8f5; - background: linear-gradient(to bottom, #dee8f5 0%,#c7d8ed 29%,#ccdcee 61%,#c0d8ef 100%); -} - - div.sceditor-group { - border: 1px solid #7596bf; - background: transparent; - padding: 0; - background: #cadcf0; - background: linear-gradient(to bottom, #cadcf0 24%,#bcd0e9 38%,#d0e1f7 99%); - } - .sceditor-button { - height: 16px; - padding: 3px 4px; - .rounded(0); - box-shadow: inset 0 1px #d5e3f1, - inset 0 -1px #e3edfb, - inset 1px 0 #cddcef, - inset -1px 0 #b8ceea; - } - .sceditor-button:first-child { .rounded(4px 0 0 4px); } - .sceditor-button:last-child { .rounded(0 4px 4px 0); } - .sceditor-button div, - .sceditor-button svg { - margin: 0; - } - .sceditor-button.active { - background: rgb(251,219,181); - background: linear-gradient(to bottom, rgba(251,219,181,1) 11%,rgba(254,180,86,1) 29%,rgba(253,235,159,1) 99%); - box-shadow: inset 0 1px #ebd1b4, - inset 0 -1px #ffe47f, - inset -1px 0 #b8ceea; - } - .sceditor-button:hover { - background: #fef7d5; - background: linear-gradient(to bottom, #fef7d5 0%,#fae5a9 42%,#ffd048 42%,#ffe59f 100%); - box-shadow: inset 0 1px #fffbe8, - inset -1px 0 #ffefc4, - inset 0 -1px #fff9cc; - } - .sceditor-button:active { - background: #e7a66d; - background: linear-gradient(to bottom, #e7a66d 0%,#fcb16d 1%,#ff8d05 42%,#ffc450 100%); - box-shadow: inset 0 1px 1px #7b6645, - inset 0 -1px #d19c33; - } - .sceditor-button.active:hover { - background: #dba368; - background: linear-gradient(to bottom, #dba368 0%,#ffbd79 4%,#fea335 34%,#ffc64c 66%,#fee069 100%); - box-shadow: inset 0 1px 1px #9e8255, - inset 0 -1px #fcce6b; - } diff --git a/src/themes/office.less b/src/themes/office.less deleted file mode 100644 index 13b50d0be..000000000 --- a/src/themes/office.less +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ - -@import "office-toolbar.less"; - -.sceditor-container { - background: rgb(163,194,234); - background: linear-gradient(to bottom, rgba(163,194,234,1) 0%,rgba(109,146,193,1) 39%,rgba(87,127,179,1) 64%,rgba(101,145,204,1) 100%); -} - - -.sceditor-container iframe, -.sceditor-container textarea { - border: 1px solid #646464; - background: #fff; - margin: 7px 40px; - padding: 20px; - width: ~"calc(100% - 120px) !important"; - box-shadow: 1px 1px 5px #293a52; -} diff --git a/src/themes/sceditor.scss b/src/themes/sceditor.scss new file mode 100644 index 000000000..05bcd66de --- /dev/null +++ b/src/themes/sceditor.scss @@ -0,0 +1,103 @@ +/*! SCEditor | (C) 2011-2024, Sam Clarke | sceditor.com/license */ +/** + * Default SCEditor + * http://www.sceditor.com/ + * + * Copyright (C) 2011-24, Sam Clarke + * + * SCEditor is licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + */ + +.sceditor-container, +.sceditor-container div, +div.sceditor-dropdown, +div.sceditor-dropdown div { + padding: 0; + margin: 0; + z-index: 3; +} + +.sceditor-container iframe, +.sceditor-container textarea { + display: block; + -ms-flex: 1 1 0%; + flex: 1 1 0%; + line-height: 1.25; + border: 0; + outline: none; + padding: 0; + margin: 5px; + resize: none; + height: auto !important; + width: auto !important; + // Allow iframes to shrink + min-height: 1px; +} + +.sceditor-container textarea { + margin: 7px 5px; +} + +div.sceditor-dnd-cover { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: rgba(255,255,255, 0.2); + border: 5px dashed #aaa; + z-index: 200; + font-size: 2em; + text-align: center; + color: #aaa; +} + +div.sceditor-grip { + overflow: hidden; + width: 10px; + height: 10px; + cursor: pointer; + position: absolute; + bottom: 0; + right: 0; + z-index: 3; + line-height: 0; +} + +.sceditor-color-column { + float: left; +} + +.sceditor-color-option { + display:block; + width: 18px; + height: 18px; + overflow: hidden; + border: 1px solid rgba(255,255,255, 0.2); +} + +.sceditor-color-option:hover { + border: 2px dotted; +} + +.sceditor-button { + .fa-stack { + display: inline; + line-height: inherit; + } + + .fa-badge { + position: absolute; + right: -14px; + top: 4px; + } + + .fa-stack-1x { + top: -4px; + } +} + +.sceditor-button-reply { + display:none!important +} \ No newline at end of file diff --git a/src/themes/square.less b/src/themes/square.less deleted file mode 100644 index 3816010d1..000000000 --- a/src/themes/square.less +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Square theme - * - * This theme is best suited to short toolbars that - * don't span multiple lines. - * - * Copyright (C) 2012, Sam Clarke (samclarke.com) - * - * SCEditor is licensed under the MIT license: - * http://www.opensource.org/licenses/mit-license.php - * - * Icons by Mark James (http://www.famfamfam.com/lab/icons/silk/) - * Licensed under the Creative Commons CC-BY license (http://creativecommons.org/licenses/by/3.0/) - */ - -@import "default.less"; - -.sceditor-container { - border: 1px solid #d6d6d6; - .rounded(0); -} - - .sceditor-container textarea { - font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; - background: #2e3436; - color: #fff; - margin: 0; - padding: 5px; - } - - div.sceditor-toolbar, div.sceditor-group { - background: #f2f2f2; - background: linear-gradient(to bottom, #f2f2f2 0%,#dddddd 89%); - } - - div.sceditor-toolbar { - padding: 0; - border-bottom: 1px solid #bbb; - background-size: 100% 32px; - } - div.sceditor-group { - margin: 0; - padding: 2px 4px; - border: 0; - border-right: 1px solid #ccc; - border-left: 1px solid #eaeaea; - .rounded(0); - } - div.sceditor-group:last-child { border-right: 0; } - div.sceditor-group:first-child { border-left: 0; } - .sceditor-button { - height: 16px; - padding: 5px; - margin: 1px; - - .rounded(0); - } - .sceditor-button div, - .sceditor-button svg { - margin: 0; - } - .sceditor-button.active, - .sceditor-button:hover, - .sceditor-button:active, - .sceditor-button.active:hover { - margin: 0; - box-shadow: none; - } - - .sceditor-button.active { - background: #f4f4f4; - border: 1px solid #ccc; - } - .sceditor-button:hover { - background: #fefefe; - border: 1px solid #ddd; - } - .sceditor-button.disabled:hover { - margin: 1px; - border: 0; - } - .sceditor-button:active { - background: #eee; - border: 1px solid #ccc; - } - .sceditor-button.active:hover { - background: #f8f8f8; - border: 1px solid #ddd; - } diff --git a/tests/.eslintrc.json b/tests/.eslintrc.json index 337f808cf..1a0815cc4 100644 --- a/tests/.eslintrc.json +++ b/tests/.eslintrc.json @@ -18,10 +18,6 @@ "strict": "off", "max-params": "off", "max-depth": ["error", 6], - "max-len": ["error", { - "code": 120, - "ignoreUrls": true, - "ignoreRegExpLiterals": true - }] + "max-len": "off" } } \ No newline at end of file diff --git a/tests/manual/debug/index.html b/tests/manual/debug/index.html index c91c7937c..637629d2a 100644 --- a/tests/manual/debug/index.html +++ b/tests/manual/debug/index.html @@ -19,7 +19,6 @@ - diff --git a/tests/unit/formats/bbcode.js b/tests/unit/formats/bbcode.js index b382d899f..c3ed0b2de 100644 --- a/tests/unit/formats/bbcode.js +++ b/tests/unit/formats/bbcode.js @@ -48,7 +48,7 @@ QUnit.test('From BBCode method as fragment', function (assert) { true ), 'line1test' + - '
      line2
      ' + + '
      line2
      ' + 'line3test', 'Should not wrap inlines with a block in between' ); @@ -76,9 +76,9 @@ QUnit.test('From BBCode method as fragment', function (assert) { '[center]line1[/center][center]line2[/center][center]line3[/center]', true ), - '
      line1
      ' + - '
      line2
      ' + - '
      line3
      ', + '
      line1
      ' + + '
      line2
      ' + + '
      line3
      ', 'Should keep all styled blocks created by a BBCode' ); @@ -106,7 +106,9 @@ QUnit.test('BBcode to HTML trim', function (assert) { this.format.toHtml( '\n\n[quote]test[/quote]\n\n' ), - '
      test
      ', + '
      ' + + '' + 'test' + + '
      ', 'Block level' ); @@ -135,7 +137,8 @@ QUnit.test('HTML to BBCode trim', function (assert) { assert.equal( this.htmlToBBCode('


      ' + - '
      test


      '), + '
      ' + + '' + 'test


      '), '[quote]test[/quote]', 'Block level' ); @@ -208,10 +211,10 @@ QUnit.test('Remove empty', function (assert) { QUnit.test('Should not remove whitespace in code tags', function (assert) { var result = this.htmlToBBCode( - '
      Some    White \n   \n   space
      ' + '
      Some    White \n   \n   space
      ' ); - assert.equal(result, '[code]Some White \n \n space[/code]\n'); + assert.equal(result, '[code=markup]Some White \n \n space[/code]\n', 'Should not remove whitespace in code tags'); }); QUnit.test('Should remove whitespace in non-code tags', function (assert) { @@ -298,7 +301,7 @@ QUnit.test('New line handling', function (assert) { '

      ' + '
      • text
      ' ), - 'text\n\n[ul]\n[li]text[/li]\n[/ul]\n', + 'text\n\n[list]\n[li]text[/li]\n[/list]\n', 'Div siblings with a list' ); @@ -309,7 +312,7 @@ QUnit.test('New line handling', function (assert) { '

      ' + '
      • text
      ' ), - 'text\n\n\n[ul]\n[li]text[/li]\n[/ul]\n', + 'text\n\n\n[list]\n[li]text[/li]\n[/list]\n', 'Multiple div siblings with a list' ); @@ -329,16 +332,16 @@ QUnit.test('New line handling', function (assert) { this.htmlToBBCode( '
      • newline

      ' ), - '[ul]\n[li]newline\n[/li]\n[/ul]\n', + '[list]\n[li]newline\n[/li]\n[/list]\n', 'List item last child block level' ); assert.equal( this.htmlToBBCode( - '
      newline
      ' + + '
      newline
      ' + '
      newline
      ' ), - '[code]newline[/code]\nnewline', + '[code=markup]newline[/code]\nnewline', 'Block level last child' ); }); @@ -625,13 +628,13 @@ QUnit.test('colour', function (assert) { QUnit.test('List', function (assert) { assert.equal( this.htmlToBBCode('
      • test
      '), - '[ul]\n[li]test[/li]\n[/ul]\n', + '[list]\n[li]test[/li]\n[/list]\n', 'UL tag' ); assert.equal( this.htmlToBBCode('
      1. test
      '), - '[ol]\n[li]test[/li]\n[/ol]\n', + '[list=I]\n[li]test[/li]\n[/list]\n', 'OL tag' ); @@ -645,7 +648,7 @@ QUnit.test('List', function (assert) { '' + '' ), - '[ul]\n[li]test\n[ul]\n[li]sub[/li]\n[/ul]\n[/li]\n[/ul]\n', + '[list]\n[li]test\n[list]\n[li]sub[/li]\n[/list]\n[/li]\n[/list]\n', 'Nested UL tag' ); }); @@ -667,15 +670,6 @@ QUnit.test('Table', function (assert) { }); -QUnit.test('Emoticons', function (assert) { - assert.equal( - this.htmlToBBCode(''), - ':)', - 'Img tag' - ); -}); - - QUnit.test('Horizontal rule', function (assert) { assert.equal( this.htmlToBBCode('
      '), @@ -686,14 +680,6 @@ QUnit.test('Horizontal rule', function (assert) { QUnit.test('Image', function (assert) { - assert.equal( - this.htmlToBBCode( - '' - ), - '[img=10x10]http://example.com/test.png[/img]', - 'Image tag with width and height attributes' - ); - assert.equal( this.htmlToBBCode( '' @@ -779,14 +765,19 @@ QUnit.test('Email', function (assert) { QUnit.test('Quote', function (assert) { assert.equal( - this.htmlToBBCode('
      Testing 1.2.3....
      '), + this.htmlToBBCode('
      ' + + '' + 'Testing 1.2.3....' + + '
      '), '[quote]Testing 1.2.3....[/quote]\n', 'Simple quote' ); assert.equal( this.htmlToBBCode( - '
      adminTesting 1.2.3....
      ' + '
      ' + + '' + + 'admin' + + 'Testing 1.2.3....
      ' ), '[quote=admin]Testing 1.2.3....[/quote]\n', 'Quote with cite (author)' @@ -794,12 +785,14 @@ QUnit.test('Quote', function (assert) { assert.equal( this.htmlToBBCode( - '
      ' + - 'adminTesting 1.2.3....' + - '
      ' + - 'adminTesting 1.2.3....' + - '
      ' + - '
      ' + '
      ' + + '' + + 'adminTesting 1.2.3....' + + '
      ' + + '' + + 'adminTesting 1.2.3....' + + '
      ' + + '
      ' ), '[quote=admin]Testing 1.2.3....\n[quote=admin]Testing 1.2.3....' + '[/quote]\n[/quote]\n', @@ -808,10 +801,11 @@ QUnit.test('Quote', function (assert) { assert.equal( this.htmlToBBCode( - '
      ' + - 'admin' + + '
      ' + + '' + + 'admin' + 'this should be ignored Testing 1.2.3....' + - '
      ' + '
      ' ), '[quote=admin]this should be ignored Testing 1.2.3....[/quote]\n', 'Quote with 2 cites (author)' @@ -821,67 +815,51 @@ QUnit.test('Quote', function (assert) { QUnit.test('Code', function (assert) { assert.equal( - this.htmlToBBCode('Testing 1.2.3....'), - '[code]Testing 1.2.3....[/code]\n', + this.htmlToBBCode('
      Testing 1.2.3....
      '), + '[code=markup]Testing 1.2.3....[/code]\n', 'Simple code' ); assert.equal( this.htmlToBBCode( - 'ignore this Testing 1.2.3....' + '
      ignore this Testing 1.2.3....
      ' ), - '[code]ignore this Testing 1.2.3....[/code]\n', + '[code=markup]ignore this Testing 1.2.3....[/code]\n', 'Code with styling' ); assert.equal( this.htmlToBBCode( - 'test' + '
      test
      ' ), - '[code]test[/code]\n', + '[code=markup]test[/code]\n', 'Code with inline styling' ); assert.equal( this.htmlToBBCode( - '
      test
      ' + '
      test
      ' ), - '[code]test[/code]\n', + '[code=markup]test[/code]\n', 'Code with block styling' ); assert.equal( this.htmlToBBCode( - '
      test
      ' + '
      test
      ' ), - '[code]test[/code]\n', + '[code=markup]test[/code]\n', 'Code with nested block styling' ); assert.equal( this.htmlToBBCode( - '
      line 1
      line 2
      ' + '
      line 1
      line 2
      ' ), - '[code]line 1\nline 2[/code]\n', + '[code=markup]line 1\nline 2[/code]\n', 'Code with block lines' ); - - assert.equal( - this.htmlToBBCode( - 'test' - ), - '[code]test[/code]\n', - 'Code with styling' - ); - - assert.equal( - this.htmlToBBCode( - '' - ), - '[code]:)[/code]\n', - 'Code with emoticon' - ); }); @@ -943,40 +921,10 @@ QUnit.test('Justify', function (assert) { 'Align attribute' ); }); - - +/* QUnit.test('YouTube', function (assert) { assert.equal( this.htmlToBBCode(''), - '[youtube]xyz[/youtube]' + '[youtube]https://www.youtube.com/watch?v=xyz[/youtube]' ); -}); - - -QUnit.test('Allow changing BBCode properties after creation', function (assert) { - // This is for backwards compatibility and will change in the next breaking - // release - - this.parser = new $.sceditor.BBCodeParser({ - quoteType: function (str) { - return '\'' + - str.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + - '\''; - } - }); - - var oldFormat = sceditor.formats.bbcode.get('quote').format; - sceditor.formats.bbcode.set('quote', { - format: 'new format' - }); - - assert.equal( - this.htmlToBBCode('
      Testing 1.2.3....
      '), - 'new format' - ); - - // Reset [quote]'s default format - sceditor.formats.bbcode.set('quote', { - format: oldFormat - }); -}); +});*/ diff --git a/tests/unit/formats/bbcode.parser.js b/tests/unit/formats/bbcode.parser.js index 55cfb945a..5bbbd71a8 100644 --- a/tests/unit/formats/bbcode.parser.js +++ b/tests/unit/formats/bbcode.parser.js @@ -255,7 +255,7 @@ QUnit.test('Do not strip start and end spaces', function (assert) { this.parser.toHTML('\n\n[quote]test[/quote]\n\n\n\n'), '

      \n' + '

      \n' + - '
      test
      ' + + '
      test
      ' + '

      \n' + '

      \n' + '


      \n' @@ -266,33 +266,32 @@ QUnit.test('Do not strip start and end spaces', function (assert) { QUnit.test('New Line Handling', function (assert) { assert.htmlEqual( this.parser.toHTML('[list][*]test\n[*]test2\nline\n[/list]'), - '
        ' + - '
      • test
      • ' + - '
      • test2
        line
      • ' + + '
      • test
      • ' + + '
      • test2
        ' + + 'line
      • ' + '
      ', - 'List with non-closed [*]' ); assert.htmlEqual( - this.parser.toHTML('[code]test\nline\n[/code]'), - 'test
      line

      ', + this.parser.toHTML('[code=markup]test\nline\n[/code]'), + '
      test
      line
      ', 'Code test' ); assert.htmlEqual( this.parser.toHTML('[quote]test\nline\n[/quote]'), - '
      test
      line

      ', + '
      test
      line
      ', 'Quote test' ); assert.htmlEqual( this.parser.toHTML('[quote][center]test[/center][/quote]'), - '
      ' + - '
      test
      ' + - '
      ', + '
      ' + + '
      test
      ' + + '
      ', 'Two block-level elements together' ); @@ -736,19 +735,19 @@ QUnit.test('Font colour', function (assert) { QUnit.test('List', function (assert) { assert.htmlEqual( this.parser.toHTML('[ul][li]test[/li][/ul]'), - '
      • test
      ', + '
      • test
      ', 'UL' ); assert.htmlEqual( this.parser.toHTML('[ol][li]test[/li][/ol]'), - '
      1. test
      ', + '
      1. test
      ', 'OL' ); assert.htmlEqual( this.parser.toHTML('[ul][li]test[ul][li]sub[/li][/ul][/li][/ul]'), - '
      • test
        • sub
      ', + '
      • test
        • sub
      ', 'Nested UL' ); }); @@ -758,8 +757,8 @@ QUnit.test('Table', function (assert) { assert.htmlEqual( this.parser.toHTML('[table][tr][th]test[/th][/tr]' + '[tr][td]data1[/td][/tr][/table]'), - '
      ' + - '
      test
      data1
      \n', + '
      ' + + '
      test
      data1
      \n', 'Normal' ); }); @@ -776,27 +775,27 @@ QUnit.test('Horizontal rule', function (assert) { QUnit.test('Image', function (assert) { assert.htmlEqual( - this.parser.toHTML('[img=10x10]http://test.com/test.png[/img]'), - '
      \n', + this.parser.toHTML('[img]http://test.com/test.png[/img]'), + '
      http://test.com/test.png
      \n', 'Normal' ); assert.htmlEqual( this.parser.toHTML('[img width=10]http://test.com/test.png[/img]'), - '
      \n', + '
      http://test.com/test.png
      \n', 'Width only' ); assert.htmlEqual( this.parser.toHTML('[img height=10]http://test.com/test.png[/img]'), - '
      \n', + '
      http://test.com/test.png
      \n', 'Height only' ); assert.htmlEqual( this.parser.toHTML('[img]http://test.com/test.png[/img]'), - '
      \n', + '
      http://test.com/test.png
      \n', 'No size' ); @@ -805,7 +804,7 @@ QUnit.test('Image', function (assert) { '[img]http://test.com/test.png?test&&test[/img]' ), '
      \n', + ' alt="http://test.com/test.png?test&&test" class="img-user-posted img-thumbnail" />
      \n', 'Ampersands in URL' ); }); @@ -814,26 +813,26 @@ QUnit.test('Image', function (assert) { QUnit.test('URL', function (assert) { assert.htmlEqual( this.parser.toHTML('[url=http://test.com/]test[/url]'), - '\n', + '\n', 'Normal' ); assert.htmlEqual( this.parser.toHTML('[url]http://test.com/[/url]'), - '\n', + '\n', 'Only URL' ); assert.htmlEqual( this.parser.toHTML('[url=http://test.com/?test&&test]test[/url]'), - '
      ' + + '\n', 'Ampersands in URL' ); assert.htmlEqual( this.parser.toHTML('[url]http://test.com/?test&&test[/url]'), - '
      ' + + '\n', 'Ampersands in URL' ); @@ -858,13 +857,13 @@ QUnit.test('Email', function (assert) { QUnit.test('Quote', function (assert) { assert.htmlEqual( this.parser.toHTML('[quote]Testing 1.2.3....[/quote]'), - '
      Testing 1.2.3....
      ', + '
      Testing 1.2.3....
      ', 'Normal' ); assert.htmlEqual( this.parser.toHTML('[quote=admin]Testing 1.2.3....[/quote]'), - '
      adminTesting 1.2.3....
      ', + '
      Testing 1.2.3....admin
      ', 'With author' ); }); @@ -872,14 +871,14 @@ QUnit.test('Quote', function (assert) { QUnit.test('Code', function (assert) { assert.htmlEqual( - this.parser.toHTML('[code]Testing 1.2.3....[/code]'), - 'Testing 1.2.3....
      ', + this.parser.toHTML('[code=markup]Testing 1.2.3....[/code]'), + '
      Testing 1.2.3....
      ', 'Normal' ); assert.htmlEqual( - this.parser.toHTML('[code]Testing [b]test[/b][/code]'), - 'Testing [b]test[/b]
      ', + this.parser.toHTML('[code=markup]Testing [b]test[/b][/code]'), + '
      Testing [b]test[/b]
      ', 'Normal' ); }); @@ -888,7 +887,7 @@ QUnit.test('Code', function (assert) { QUnit.test('Left', function (assert) { assert.htmlEqual( this.parser.toHTML('[left]Testing 1.2.3....[/left]'), - '
      Testing 1.2.3....
      ', + '
      Testing 1.2.3....
      ', 'Normal' ); }); @@ -897,7 +896,7 @@ QUnit.test('Left', function (assert) { QUnit.test('Right', function (assert) { assert.htmlEqual( this.parser.toHTML('[right]Testing 1.2.3....[/right]'), - '
      Testing 1.2.3....
      ', + '
      Testing 1.2.3....
      ', 'Normal' ); }); @@ -906,7 +905,7 @@ QUnit.test('Right', function (assert) { QUnit.test('Centre', function (assert) { assert.htmlEqual( this.parser.toHTML('[center]Testing 1.2.3....[/center]'), - '
      Testing 1.2.3....
      ', + '
      Testing 1.2.3....
      ', 'Normal' ); }); @@ -915,22 +914,22 @@ QUnit.test('Centre', function (assert) { QUnit.test('Justify', function (assert) { assert.htmlEqual( this.parser.toHTML('[justify]Testing 1.2.3....[/justify]'), - '
      Testing 1.2.3....
      ', + '
      Testing 1.2.3....
      ', 'Normal' ); }); -QUnit.test('YouTube', function (assert) { +/*QUnit.test('YouTube', function (assert) { assert.htmlEqual( - this.parser.toHTML('[youtube]xyz[/youtube]'), + this.parser.toHTML('[youtube]https://www.youtube.com/watch?v=xyz[/youtube]'), '
      \n', 'Normal' ); -}); +});*/ QUnit.module('formats/bbcode#Parser - XSS', { @@ -945,7 +944,7 @@ QUnit.test('[img]', function (assert) { this.parser.toHTML('[img]fake.png" onerror="alert(' + 'String.fromCharCode(88,83,83))[/img]'), '
      \n', + 'String.fromCharCode(88,83,83))" alt="fake.png" onerror="alert(String.fromCharCode(88,83,83))" class="img-user-posted img-thumbnail" />
      \n', 'Inject attribute' ); @@ -981,46 +980,10 @@ QUnit.test('[img]', function (assert) { ), 'Nested [img]' ); - - assert.equal( - this.parser.toHTML('[img=\'"2]uri[/img]'), - '
      ' + - '
      \n', - 'Dimension attribute injection' - ); - - assert.equal( - this.parser.toHTML('[img=\'"2x3]uri[/img]'), - '
      \n', - 'Width attribute injection' - ); - - assert.equal( - this.parser.toHTML('[img=3x\'"2]uri[/img]'), - '
      \n', - 'Width attribute injection' - ); }); QUnit.test('[url]', function (assert) { - assert.equal( - this.parser.toHTML( - '[url]fake.png" ' + - 'onmouseover="alert(String.fromCharCode(88,83,83))[/url]' - ), - - '\n', - - 'Inject attribute' - ); - assert.ok( !/href="javascript:/i.test( this.parser.toHTML('[url]javascript:alert(' + @@ -1054,7 +1017,7 @@ QUnit.test('[url]', function (assert) { assert.equal( this.parser.toHTML('[url]test@test.testtet[/url]'), - '
      ' + + '\n', 'Inject HTML' ); @@ -1067,7 +1030,7 @@ QUnit.test('[url]', function (assert) { '\n', 'Inject HTML' @@ -1137,8 +1100,8 @@ QUnit.test('HTML injection', function (assert) { assert.equal( this.parser.toHTML('[quote=testtesttest]test[/quote]'), - '
      test<b>test</b>test' + - 'test
      ', + '
      testtest<b>test</b>test' + + '
      ', 'Inject HTML script' ); }); diff --git a/tests/unit/lib/SCEditor.js b/tests/unit/lib/SCEditor.js index fce767fff..7624690f4 100644 --- a/tests/unit/lib/SCEditor.js +++ b/tests/unit/lib/SCEditor.js @@ -442,40 +442,7 @@ QUnit.test('updateOriginal()', function (assert) { sceditor.getRangeHelper().clear(); sceditor.updateOriginal(); - assert.htmlEqual(textarea.value, '
      text 1234...
      '); -}); - - -QUnit.test('emoticons()', function (assert) { - var $body = $(sceditor.getBody()); - - sceditor.emoticons(true); - sceditor.val('

      Testing :) :( 123...

      '); - - assert.equal($body.find('img[data-sceditor-emoticon]').length, 2); - - sceditor.emoticons(false); - - assert.equal($body.find('img[data-sceditor-emoticon]').length, 0); -}); - -QUnit.test('emoticons() - Longest first', function (assert) { - reloadEditor({ - emoticons: { - dropdown: { - '>:(': 'emoticons/angry.png', - ':(': 'emoticons/sad.png' - } - } - }); - - var $body = $(sceditor.getBody()); - - sceditor.emoticons(true); - sceditor.val('

      Testing :( >:(

      '); - - assert.equal($body.find('img[data-sceditor-emoticon=">:("]').length, 1); - assert.equal($body.find('img[data-sceditor-emoticon=":("]').length, 1); + assert.htmlEqual(textarea.value, 'text 1234...'); }); QUnit.test('Insert image XSS', function (assert) { @@ -535,10 +502,10 @@ QUnit.test('Code tags should ignore block styling', function (assert) { format: 'bbcode' }); sceditor.css('code {text-align: left}'); - sceditor.val('[code]test[/code]'); + sceditor.val('[code=markup]test[/code]'); setTimeout(() => { - assert.equal(sceditor.val(), '[code]test[/code]\n'); + assert.equal(sceditor.val(), '[code=markup]test[/code]\n'); done(); }, 100); }); diff --git a/tests/unit/lib/dom.js b/tests/unit/lib/dom.js index 234628ec6..2bfdb606d 100644 --- a/tests/unit/lib/dom.js +++ b/tests/unit/lib/dom.js @@ -653,14 +653,14 @@ QUnit.test('fixNesting() - Paragraph with blockquote', function (assert) { assert.nodesEqual( root, utils.htmlToDiv( - '

      1

      2

      3

      ' + '

      1

      2

      3

      ' ) ); }); QUnit.test('fixNesting() - Do not create empty nodes', function (assert) { var node = utils.htmlToDiv( - '
      test
      ' + '
      test
      ' ); dom.fixNesting(node); @@ -668,13 +668,13 @@ QUnit.test('fixNesting() - Do not create empty nodes', function (assert) { assert.nodesEqual( node, utils.htmlToDiv( - '
      test
      ' + '
      test
      ' ) ); }); QUnit.test('fixNesting() - Create nodes with a child that cannot have children', function (assert) { var node = utils.htmlToDiv( - '
      test

      ' + '
      test

      ' ); dom.fixNesting(node); @@ -682,14 +682,14 @@ QUnit.test('fixNesting() - Create nodes with a child that cannot have children', assert.nodesEqual( node, utils.htmlToDiv( - '
      test

      ' + '
      test

      ' ) ); }); QUnit.test('fixNesting() - Do not create empty nodes when deeply nested', function (assert) { var node = utils.htmlToDiv( - '
      test
      ' + '
      test
      ' ); dom.fixNesting(node); @@ -697,14 +697,14 @@ QUnit.test('fixNesting() - Do not create empty nodes when deeply nested', functi assert.nodesEqual( node, utils.htmlToDiv( - '
      test
      ' + '
      test
      ' ) ); }); QUnit.test('fixNesting() - Do not create empty nodes when inline styling nested', function (assert) { var node = utils.htmlToDiv( - '
      4
      ' + '
      4
      ' ); dom.fixNesting(node); @@ -712,7 +712,7 @@ QUnit.test('fixNesting() - Do not create empty nodes when inline styling nested' assert.nodesEqual( node, utils.htmlToDiv( - '
      4
      ' + '
      4
      ' ) ); }); @@ -720,7 +720,7 @@ QUnit.test('fixNesting() - Do not create empty nodes when inline styling nested' QUnit.test('fixNesting() - Preserve inline styling', function (assert) { // Below is the following HTML (have to do it manually due to

      being // closed by the

      when using innerHTML): - //

      1

      2

      3
      4

      5

      + //

      1

      2

      3
      4

      5

      var p1 = document.createElement('p'); p1.appendChild(document.createTextNode('1')); @@ -753,7 +753,7 @@ QUnit.test('fixNesting() - Preserve inline styling', function (assert) { utils.htmlToDiv( '

      1

      ' + '

      2

      ' + - '
      3
      ' + + '
      3
      ' + '

      4

      ' + '

      5

      ' ) @@ -762,7 +762,7 @@ QUnit.test('fixNesting() - Preserve inline styling', function (assert) { QUnit.test('fixNesting() - Preserve inline styling', function (assert) { var node = utils.htmlToDiv( - '1

      2

      3
      ' + '1

      2

      3
      ' ); dom.fixNesting(node); @@ -771,7 +771,7 @@ QUnit.test('fixNesting() - Preserve inline styling', function (assert) { node, utils.htmlToDiv( '1' + - '

      2

      ' + + '

      2

      ' + '3' ) ); @@ -779,7 +779,7 @@ QUnit.test('fixNesting() - Preserve inline styling', function (assert) { QUnit.test('fixNesting() - Preserve inline styling nested', function (assert) { var node = utils.htmlToDiv( - '1
      23
      4
      5
      6
      7
      ' + '1
      23
      4
      5
      6
      7
      ' ); dom.fixNesting(node); @@ -793,7 +793,7 @@ QUnit.test('fixNesting() - Preserve inline styling nested', function (assert) { '2' + '3' + '' + - '
      4
      ' + + '
      4
      ' + '' + '5' + '6' +