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 support for multiple projectors.
|
||||||
- Added an overlay for the current list of speakers.
|
- Added an overlay for the current list of speakers.
|
||||||
- Added button to clear the chatbox.
|
- Added button to clear the chatbox.
|
||||||
|
- Switched editor back from TinyMCE to CKEditor which provides a
|
||||||
|
better copy/paste support from MS Word.
|
||||||
|
|
||||||
Motions:
|
Motions:
|
||||||
- Added origin field.
|
- Added origin field.
|
||||||
|
@ -196,7 +196,7 @@ OpenSlides uses the following projects or parts of them:
|
|||||||
* `bootstrap <http://getbootstrap.com>`_, License: MIT
|
* `bootstrap <http://getbootstrap.com>`_, License: MIT
|
||||||
* `bootstrap-ui-datetime-picker <https://github.com/Gillardo/bootstrap-ui-datetime-picker>`_, License: MIT
|
* `bootstrap-ui-datetime-picker <https://github.com/Gillardo/bootstrap-ui-datetime-picker>`_, License: MIT
|
||||||
* `chosen <http://harvesthq.github.io/chosen/>`_, 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
|
* `font-awesome-bower <https://github.com/tdg5/font-awesome-bower>`_, License: MIT
|
||||||
* `jquery <https://jquery.com>`_, License: MIT
|
* `jquery <https://jquery.com>`_, License: MIT
|
||||||
* `jquery.cookie <https://plugins.jquery.com/cookie>`_, 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
|
* `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
|
* `pdfjs-dist <http://mozilla.github.io/pdf.js/>`_, License: Apache-2.0
|
||||||
* `roboto-condensed <https://github.com/davidcunningham/roboto-condensed>`_, 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
|
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-Regular.woff",
|
||||||
"fonts/Roboto-Condensed/Roboto-Condensed-Light.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": {
|
"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')));
|
.pipe(gulp.dest(path.join(output_directory, 'css')));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Extra task only for CKEditor
|
// CKEditor defaults
|
||||||
gulp.task('ckeditor', function () {
|
gulp.task('ckeditor-defaults', function () {
|
||||||
return gulp.src(path.join('bower_components', 'ckeditor', '**'))
|
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')));
|
.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
|
// Compiles translation files (*.po) to *.json and saves them in the directory
|
||||||
// openslides/static/i18n/.
|
// openslides/static/i18n/.
|
||||||
@ -126,7 +173,16 @@ gulp.task('translations', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Gulp default task. Runs all other tasks before.
|
// 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,18 +548,29 @@ 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.
|
// 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', [
|
.factory('Editor', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
function(gettextCatalog) {
|
function (gettextCatalog) {
|
||||||
return {
|
return {
|
||||||
getOptions: function (images) {
|
getOptions: function (images) {
|
||||||
return {
|
return {
|
||||||
on: {
|
on: {
|
||||||
instanceReady: function() {
|
instanceReady: function() {
|
||||||
// add a listener to ckeditor that parses the clipboard content and, after the regular filter,
|
// This adds a listener to ckeditor to remove unwanted blank lines on import.
|
||||||
// additionally strips out all empty <p> paragraphs
|
// Clipboard content varies heavily in structure and html code, depending on the "sender".
|
||||||
// TODO: check all kind of clipboard html content if "isEmpty" is a reliable property
|
// 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) {
|
this.on('paste', function(evt) {
|
||||||
if (evt.data.type == 'html') {
|
if (evt.data.type == 'html') {
|
||||||
var fragment = CKEDITOR.htmlParser.fragment.fromHtml(evt.data.dataValue);
|
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'.
|
// html content will now be in a dom-like structure inside 'fragment'.
|
||||||
this.filter.applyTo(fragment);
|
this.filter.applyTo(fragment);
|
||||||
if (fragment.children) {
|
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 = [];
|
var new_content_children = [];
|
||||||
for (var i = 0; i < fragment.children.length; i++) {
|
_.forEach(fragment.children, function (child) {
|
||||||
var empty = true;
|
var empty = true;
|
||||||
if (fragment.children[i].children){
|
if (child.children){
|
||||||
for (var j = 0; j < fragment.children[i].children.length; j++) {
|
_.forEach(child.children, function(grandchild) {
|
||||||
var child = fragment.children[i].children[j];
|
if (grandchild.name != 'p' && grandchild.name != 'br') {
|
||||||
if (child.name != 'p' && child.name != 'br') {
|
|
||||||
empty = false;
|
empty = false;
|
||||||
} else if (child.isEmpty !== true) {
|
} else if (grandchild.isEmpty !== true) {
|
||||||
empty = false;
|
empty = false;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
if (empty === false) {
|
if (empty === false) {
|
||||||
new_content_children.push(fragment.children[i]);
|
new_content_children.push(child);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fragment.children[i].name != 'p' && fragment.children[i].name != 'br' &&
|
if (child.name != 'p' && child.name != 'br' &&
|
||||||
fragment.children[i].isEmpty !== true){
|
child.isEmpty !== true){
|
||||||
new_content_children.push(fragment.children[i]);
|
new_content_children.push(child);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
fragment.children = new_content_children;
|
fragment.children = new_content_children;
|
||||||
}
|
}
|
||||||
fragment.writeHtml(writer);
|
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();
|
evt.data.dataValue = writer.getHtml();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -10,19 +10,14 @@
|
|||||||
<link rel="stylesheet" href="static/css/openslides-libs.css">
|
<link rel="stylesheet" href="static/css/openslides-libs.css">
|
||||||
<link rel="stylesheet" href="static/css/app.css">
|
<link rel="stylesheet" href="static/css/app.css">
|
||||||
<link rel="icon" href="/static/img/favicon.png">
|
<link rel="icon" href="/static/img/favicon.png">
|
||||||
<!-- TODO: there is probably a better place for it:-->
|
<!-- TODO (#2787): move into openslides-libs-->
|
||||||
<script>
|
<script>
|
||||||
window.CKEDITOR_BASEPATH = '/static/ckeditor/';
|
window.CKEDITOR_BASEPATH = '/static/ckeditor/';
|
||||||
</script>
|
</script>
|
||||||
<!-- -->
|
|
||||||
<script src="static/js/openslides-libs.js"></script>
|
<script src="static/js/openslides-libs.js"></script>
|
||||||
<script src="static/js/openslides.js"></script>
|
<script src="static/js/openslides.js"></script>
|
||||||
<script src="static/js/openslides-templates.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>
|
<div id="wrapper" ng-cloak>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
@ -82,7 +82,7 @@ angular.module('OpenSlidesApp.motions.lineNumbering', [])
|
|||||||
node.setAttribute('class', 'os-line-number line-number-' + lineNumber);
|
node.setAttribute('class', 'os-line-number line-number-' + lineNumber);
|
||||||
node.setAttribute('data-line-number', lineNumber + '');
|
node.setAttribute('data-line-number', lineNumber + '');
|
||||||
node.setAttribute('contenteditable', 'false');
|
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;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user