Fixing some remarks for CKEditor PR#2770
This commit is contained in:
parent
08cb6a3d1b
commit
82396a784d
@ -24,6 +24,8 @@ Core:
|
||||
- Added support for multiple projectors.
|
||||
- Added an overlay for the current list of speakers.
|
||||
- Added button to clear the chatbox.
|
||||
- Switched editor back from TinyMCE to CKEditor which provides a
|
||||
better copy/paste support from MS Word.
|
||||
|
||||
Motions:
|
||||
- Added origin field.
|
||||
|
@ -196,7 +196,7 @@ OpenSlides uses the following projects or parts of them:
|
||||
* `bootstrap <http://getbootstrap.com>`_, License: MIT
|
||||
* `bootstrap-ui-datetime-picker <https://github.com/Gillardo/bootstrap-ui-datetime-picker>`_, License: MIT
|
||||
* `chosen <http://harvesthq.github.io/chosen/>`_, License: MIT
|
||||
* `ckeditor <http://ckeditor.com>`_, License: For licensing, see LICENSE.md or http://ckeditor.com/license.
|
||||
* `ckeditor <http://ckeditor.com>`_, License: GPL 2+, LGPL 2.1+ or MPL 1.1.
|
||||
* `font-awesome-bower <https://github.com/tdg5/font-awesome-bower>`_, License: MIT
|
||||
* `jquery <https://jquery.com>`_, License: MIT
|
||||
* `jquery.cookie <https://plugins.jquery.com/cookie>`_, License: MIT
|
||||
@ -211,8 +211,6 @@ OpenSlides uses the following projects or parts of them:
|
||||
* `open-sans-fontface <https://github.com/FontFaceKit/open-sans>`_, License: Apache License version 2.0
|
||||
* `pdfjs-dist <http://mozilla.github.io/pdf.js/>`_, License: Apache-2.0
|
||||
* `roboto-condensed <https://github.com/davidcunningham/roboto-condensed>`_, License: Apache 2.0
|
||||
* `tinymce <http://www.tinymce.com>`_, License: LGPL-2.1
|
||||
* `tinymce-i18n <https://github.com/OpenSlides/tinymce-i18n>`_, License: LGPL-2.1
|
||||
|
||||
|
||||
License and authors
|
||||
|
24
bower.json
24
bower.json
@ -55,30 +55,6 @@
|
||||
"fonts/Roboto-Condensed/Roboto-Condensed-Regular.woff",
|
||||
"fonts/Roboto-Condensed/Roboto-Condensed-Light.woff"
|
||||
]
|
||||
},
|
||||
"ckeditor": {
|
||||
"main": [
|
||||
"ckeditor.js",
|
||||
"skins/moono-lisa/*",
|
||||
"lang/en.js",
|
||||
"lang/de.js",
|
||||
"lang/pt.js",
|
||||
"lang/es.js",
|
||||
"lang/fr.js",
|
||||
"lang/cs.js",
|
||||
"plugins/about/*",
|
||||
"plugins/clipboard/*",
|
||||
"plugins/dialog/*",
|
||||
"plugins/find/*",
|
||||
"plugins/image/*",
|
||||
"plugins/justify/*",
|
||||
"plugins/liststyle/*",
|
||||
"plugins/magicline/*",
|
||||
"plugins/pastefromword/*",
|
||||
"plugins/showblocks/*",
|
||||
"plugins/table/*",
|
||||
"plugins/tabletools/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
|
64
gulpfile.js
64
gulpfile.js
@ -108,12 +108,59 @@ gulp.task('angular-chosen-img', function () {
|
||||
.pipe(gulp.dest(path.join(output_directory, 'css')));
|
||||
});
|
||||
|
||||
// Extra task only for CKEditor
|
||||
gulp.task('ckeditor', function () {
|
||||
return gulp.src(path.join('bower_components', 'ckeditor', '**'))
|
||||
// CKEditor defaults
|
||||
gulp.task('ckeditor-defaults', function () {
|
||||
return gulp.src([
|
||||
path.join('bower_components', 'ckeditor', 'styles.js'),
|
||||
path.join('bower_components', 'ckeditor', 'contents.css'),
|
||||
])
|
||||
.pipe(gulp.dest(path.join(output_directory, 'ckeditor')));
|
||||
});
|
||||
|
||||
// CKEditor skins
|
||||
gulp.task('ckeditor-skins', function () {
|
||||
return gulp.src([
|
||||
path.join('bower_components', 'ckeditor', 'skins', 'moono-lisa', '**', '*'),
|
||||
],{ base: path.join('bower_components', 'ckeditor', 'skins') })
|
||||
.pipe(gulp.dest(path.join(output_directory, 'ckeditor', 'skins')));
|
||||
});
|
||||
|
||||
// CKEditor plugins
|
||||
gulp.task('ckeditor-plugins', function () {
|
||||
return gulp.src([
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'clipboard', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'colorbutton', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'dialog', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'find', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'image', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'justify', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'liststyle', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'magicline', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'pastefromword', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'panelbutton', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'showblocks', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'sourcedialog', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'table', '**', '*'),
|
||||
path.join('bower_components', 'ckeditor', 'plugins', 'tabeltools', '**', '*'),
|
||||
],{ base: path.join('bower_components', 'ckeditor', 'plugins') })
|
||||
.pipe(gulp.dest(path.join(output_directory, 'ckeditor', 'plugins')));
|
||||
});
|
||||
|
||||
// CKEditor languages
|
||||
gulp.task('ckeditor-lang', function () {
|
||||
return gulp.src([
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'en.js'),
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'de.js'),
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'pt.js'),
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'es.js'),
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'fr.js'),
|
||||
path.join('bower_components', 'ckeditor', 'lang', 'cs.js'),
|
||||
])
|
||||
.pipe(gulp.dest(path.join(output_directory, 'ckeditor', 'lang')));
|
||||
});
|
||||
|
||||
// Combines all CKEditor related tasks.
|
||||
gulp.task('ckeditor', ['ckeditor-defaults', 'ckeditor-skins', 'ckeditor-plugins', 'ckeditor-lang'], function () {});
|
||||
|
||||
// Compiles translation files (*.po) to *.json and saves them in the directory
|
||||
// openslides/static/i18n/.
|
||||
@ -126,7 +173,16 @@ gulp.task('translations', function () {
|
||||
});
|
||||
|
||||
// Gulp default task. Runs all other tasks before.
|
||||
gulp.task('default', ['js', 'js-libs', 'templates', 'css-libs', 'fonts-libs', 'ckeditor', 'angular-chosen-img', 'translations'], function () {});
|
||||
gulp.task('default', [
|
||||
'js',
|
||||
'js-libs',
|
||||
'templates',
|
||||
'css-libs',
|
||||
'fonts-libs',
|
||||
'ckeditor',
|
||||
'angular-chosen-img',
|
||||
'translations'
|
||||
], function () {});
|
||||
|
||||
|
||||
/**
|
||||
|
@ -548,7 +548,17 @@ angular.module('OpenSlidesApp.core', [
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
// Configs for CKEditor which has to set while startup of OpenSlides
|
||||
.config(
|
||||
function() {
|
||||
CKEDITOR.disableAutoInline = true;
|
||||
}
|
||||
)
|
||||
|
||||
// Options for CKEditor used in various create and edit views.
|
||||
// Required in core/base.js because MotionComment factory which used this
|
||||
// factory has to placed in motions/base.js.
|
||||
.factory('Editor', [
|
||||
'gettextCatalog',
|
||||
function (gettextCatalog) {
|
||||
@ -557,9 +567,10 @@ angular.module('OpenSlidesApp.core', [
|
||||
return {
|
||||
on: {
|
||||
instanceReady: function() {
|
||||
// add a listener to ckeditor that parses the clipboard content and, after the regular filter,
|
||||
// additionally strips out all empty <p> paragraphs
|
||||
// TODO: check all kind of clipboard html content if "isEmpty" is a reliable property
|
||||
// This adds a listener to ckeditor to remove unwanted blank lines on import.
|
||||
// Clipboard content varies heavily in structure and html code, depending on the "sender".
|
||||
// Here it is first parsed into a pseudo-DOM (two lines taken from a ckeditor
|
||||
// paste example on the ckeditor site).
|
||||
this.on('paste', function(evt) {
|
||||
if (evt.data.type == 'html') {
|
||||
var fragment = CKEDITOR.htmlParser.fragment.fromHtml(evt.data.dataValue);
|
||||
@ -567,31 +578,37 @@ angular.module('OpenSlidesApp.core', [
|
||||
// html content will now be in a dom-like structure inside 'fragment'.
|
||||
this.filter.applyTo(fragment);
|
||||
if (fragment.children) {
|
||||
// If this fragment is DOM-like, it may contain nested properties
|
||||
// (being html nodes). Traverse the children and check if it is a
|
||||
// child only containing empty <br> or <p>.
|
||||
// new_content_children will finally contain all nodes that are
|
||||
// not empty.
|
||||
var new_content_children = [];
|
||||
for (var i = 0; i < fragment.children.length; i++) {
|
||||
_.forEach(fragment.children, function (child) {
|
||||
var empty = true;
|
||||
if (fragment.children[i].children){
|
||||
for (var j = 0; j < fragment.children[i].children.length; j++) {
|
||||
var child = fragment.children[i].children[j];
|
||||
if (child.name != 'p' && child.name != 'br') {
|
||||
if (child.children){
|
||||
_.forEach(child.children, function(grandchild) {
|
||||
if (grandchild.name != 'p' && grandchild.name != 'br') {
|
||||
empty = false;
|
||||
} else if (child.isEmpty !== true) {
|
||||
} else if (grandchild.isEmpty !== true) {
|
||||
empty = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (empty === false) {
|
||||
new_content_children.push(fragment.children[i]);
|
||||
new_content_children.push(child);
|
||||
}
|
||||
} else {
|
||||
if (fragment.children[i].name != 'p' && fragment.children[i].name != 'br' &&
|
||||
fragment.children[i].isEmpty !== true){
|
||||
new_content_children.push(fragment.children[i]);
|
||||
}
|
||||
if (child.name != 'p' && child.name != 'br' &&
|
||||
child.isEmpty !== true){
|
||||
new_content_children.push(child);
|
||||
}
|
||||
}
|
||||
});
|
||||
fragment.children = new_content_children;
|
||||
}
|
||||
fragment.writeHtml(writer);
|
||||
// Return the re-created fragment without the empty <p> and <br> into the
|
||||
// editor import processing (same as at the begin of the function: by ckeditor)
|
||||
evt.data.dataValue = writer.getHtml();
|
||||
}
|
||||
});
|
||||
|
@ -10,19 +10,14 @@
|
||||
<link rel="stylesheet" href="static/css/openslides-libs.css">
|
||||
<link rel="stylesheet" href="static/css/app.css">
|
||||
<link rel="icon" href="/static/img/favicon.png">
|
||||
<!-- TODO: there is probably a better place for it:-->
|
||||
<!-- TODO (#2787): move into openslides-libs-->
|
||||
<script>
|
||||
window.CKEDITOR_BASEPATH = '/static/ckeditor/';
|
||||
</script>
|
||||
<!-- -->
|
||||
<script src="static/js/openslides-libs.js"></script>
|
||||
<script src="static/js/openslides.js"></script>
|
||||
<script src="static/js/openslides-templates.js"></script>
|
||||
<!-- TODO: move inside openslides-libs (?):-->
|
||||
<script>
|
||||
CKEDITOR.disableAutoInline = true;
|
||||
</script>
|
||||
<!-- -->
|
||||
|
||||
<div id="wrapper" ng-cloak>
|
||||
|
||||
<!-- Header -->
|
||||
|
@ -82,7 +82,7 @@ angular.module('OpenSlidesApp.motions.lineNumbering', [])
|
||||
node.setAttribute('class', 'os-line-number line-number-' + lineNumber);
|
||||
node.setAttribute('data-line-number', lineNumber + '');
|
||||
node.setAttribute('contenteditable', 'false');
|
||||
node.innerHTML = ' '; // Prevent tinymce from stripping out empty span's
|
||||
node.innerHTML = ' '; // Prevent ckeditor from stripping out empty span's
|
||||
return node;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user