mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Fixed some issues in markdown CKEDITOR plugin and remove BBCode plugin.
This commit is contained in:
parent
be8f074ca5
commit
d11a436e74
6 changed files with 26 additions and 1396 deletions
|
@ -1,168 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BBCode plugin playground – CKEditor Sample</title>
|
||||
<script src="../../../ckeditor.js"></script>
|
||||
<link href="../../../samples/old/sample.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#editables
|
||||
{
|
||||
float:left;
|
||||
width: 49%
|
||||
}
|
||||
|
||||
#preview
|
||||
{
|
||||
width: 50%;
|
||||
float:right;
|
||||
}
|
||||
|
||||
#console
|
||||
{
|
||||
height: 300px;
|
||||
padding: 5px 10px;
|
||||
border: solid 3px #555;
|
||||
overflow: auto;
|
||||
color: #000;
|
||||
transition: border-color 0.5s;
|
||||
font-family: Monaco, monospace;
|
||||
font-size: 13px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#console.updated {
|
||||
border-color: #0B0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="samples">
|
||||
CKEditor Sample — BBCode plugin playground
|
||||
</h1>
|
||||
<div id="main">
|
||||
<div class="description">
|
||||
<p>
|
||||
This sample shows how to configure CKEditor to output <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a> format instead of HTML.
|
||||
Please note that the editor configuration was modified to reflect what is needed in a BBCode editing environment.
|
||||
Smiley images, for example, were stripped to the emoticons that are commonly used in some BBCode dialects.
|
||||
</p>
|
||||
<p>
|
||||
Please note that currently there is no standard for the BBCode markup language, so its implementation
|
||||
for different platforms (message boards, blogs etc.) can vary. This means that before using CKEditor to
|
||||
output BBCode you may need to adjust the implementation to your own environment.
|
||||
</p>
|
||||
<p>
|
||||
A snippet of the configuration code can be seen below; check the source of this page for
|
||||
a full definition:
|
||||
</p>
|
||||
<pre class="samples">
|
||||
CKEDITOR.inline( 'editor1', {
|
||||
<strong>extraPlugins : 'bbcode',</strong>
|
||||
<i>(below configurations details omitted:)</i>
|
||||
toolbar : ...,
|
||||
fontSize_sizes : ...,
|
||||
smiley_images : ...,
|
||||
smiley_descriptions : ...
|
||||
});</pre>
|
||||
</div>
|
||||
|
||||
<div id="editables">
|
||||
<textarea id="editor1">
|
||||
[img]http://a.cksource.com/f/1/img/logo-ckeditor.gif[/img]
|
||||
"[b]Little Red Riding Hood[/b]" is a famous [url=http://en.wikipedia.org/wiki/Fairy_tale]fairy tale[/url] about a young girl's encounter with a wolf. The story has been changed considerably in its history and subject to numerous modern adaptations and readings.
|
||||
[list]
|
||||
[*]Chinese: [i]小紅帽[/i]
|
||||
[*]Italian: [i]Cappuccetto Rosso[/i]
|
||||
[*]Spanish: [i]Caperucita Roja[/i]
|
||||
[/list]
|
||||
[quote]It is about a girl called [color=#FF0000]Little Red Riding Hood :)[/color], after the red [url=http://en.wikipedia.org/wiki/Hood_%28headgear%29]hooded[/url] [url=http://en.wikipedia.org/wiki/Cape]cape[/url] or [url=http://en.wikipedia.org/wiki/Cloak]cloak[/url] she wears.
|
||||
The girl walks through the woods to deliver food to her sick grandmother. A wolf wants to eat the girl but is afraid to do so in public. He approaches the girl, and she naïvely tells him where she is going.
|
||||
He suggests the girl pick some flowers, which she does. In the meantime, he goes to the grandmother's house and gains entry by pretending to be the girl. He swallows the grandmother whole, and waits for the girl, disguised as the grandmother. When the girl arrives, she notices he looks very strange to be her grandma. In most retellings, this eventually culminates with Little Red Riding Hood saying, "My, what big teeth you have!"
|
||||
To which the wolf replies, "The better to eat you with," and swallows her whole, too.[/quote]
|
||||
The above version most widely known today is based on the [url=http://en.wikipedia.org/wiki/Brothers_Grimm]Brothers Grimm[/url] variant.
|
||||
</textarea>
|
||||
</div>
|
||||
<div id="preview">
|
||||
<h3 for="console">BBCode Output: </h3>
|
||||
<pre id="console">
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<hr>
|
||||
<p>
|
||||
CKEditor - The text editor for the Internet - <a class="samples" href="https://ckeditor.com/">https://ckeditor.com</a>
|
||||
</p>
|
||||
<p id="copy">
|
||||
Copyright © 2003-2019, <a class="samples" href="https://cksource.com/">CKSource</a> - Frederico
|
||||
Knabben. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var editor = CKEDITOR.replace( 'editor1', {
|
||||
extraPlugins: 'bbcode',
|
||||
// Remove unused plugins.
|
||||
removePlugins: 'bidi,dialogadvtab,div,filebrowser,flash,format,forms,horizontalrule,iframe,justify,liststyle,pagebreak,showborders,stylescombo,table,tabletools,templates',
|
||||
// Width and height are not supported in the BBCode format, so object resizing is disabled.
|
||||
disableObjectResizing: true,
|
||||
height: 250,
|
||||
toolbar: [
|
||||
['Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo'],
|
||||
['Find', 'Replace', '-', 'SelectAll', 'RemoveFormat'],
|
||||
['Link', 'Unlink', 'Image'],
|
||||
'/',
|
||||
['FontSize', 'Bold', 'Italic', 'Underline'],
|
||||
['NumberedList', 'BulletedList', '-', 'Blockquote'],
|
||||
['TextColor', '-', 'Smiley', 'SpecialChar', '-', 'Maximize']
|
||||
],
|
||||
// Define font sizes in percent values.
|
||||
fontSize_sizes: '30/30%;50/50%;100/100%;120/120%;150/150%;200/200%;300/300%',
|
||||
// Strip CKEditor smileys to those commonly used in BBCode.
|
||||
smiley_images: [
|
||||
'regular_smile.png', 'sad_smile.png', 'wink_smile.png', 'teeth_smile.png', 'tongue_smile.png',
|
||||
'embarrassed_smile.png', 'omg_smile.png', 'whatchutalkingabout_smile.png', 'angel_smile.png',
|
||||
'shades_smile.png', 'cry_smile.png', 'kiss.png'
|
||||
],
|
||||
smiley_descriptions: [
|
||||
'smiley', 'sad', 'wink', 'laugh', 'cheeky', 'blush', 'surprise',
|
||||
'indecision', 'angel', 'cool', 'crying', 'kiss'
|
||||
]
|
||||
} );
|
||||
|
||||
function updatePreview() {
|
||||
var consoleEl = CKEDITOR.document.getById( 'console' );
|
||||
consoleEl.addClass( 'updated' );
|
||||
setTimeout( function() { consoleEl.removeClass( 'updated' ); }, 500 );
|
||||
// IE needs <br>, it doesn't even understand new lines.
|
||||
consoleEl.setHtml( editor.getData().replace( /\n\r?/g, '<br>' ) );
|
||||
}
|
||||
|
||||
function checkUpdatePreview() {
|
||||
setTimeout( function() {
|
||||
if ( editor.checkDirty() ) {
|
||||
updatePreview();
|
||||
editor.resetDirty();
|
||||
}
|
||||
}, 0 );
|
||||
}
|
||||
|
||||
editor.on( 'instanceReady', updatePreview );
|
||||
editor.on( 'key', checkUpdatePreview );
|
||||
editor.on( 'selectionChange', checkUpdatePreview );
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,809 +0,0 @@
|
|||
/**
|
||||
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
*/
|
||||
|
||||
( function() {
|
||||
CKEDITOR.on( 'dialogDefinition', function( ev ) {
|
||||
var tab,
|
||||
name = ev.data.name,
|
||||
definition = ev.data.definition;
|
||||
|
||||
if ( name == 'link' ) {
|
||||
definition.removeContents( 'target' );
|
||||
definition.removeContents( 'upload' );
|
||||
definition.removeContents( 'advanced' );
|
||||
tab = definition.getContents( 'info' );
|
||||
tab.remove( 'emailSubject' );
|
||||
tab.remove( 'emailBody' );
|
||||
} else if ( name == 'image' ) {
|
||||
definition.removeContents( 'advanced' );
|
||||
tab = definition.getContents( 'Link' );
|
||||
tab.remove( 'cmbTarget' );
|
||||
tab = definition.getContents( 'info' );
|
||||
tab.remove( 'txtAlt' );
|
||||
tab.remove( 'basic' );
|
||||
}
|
||||
} );
|
||||
|
||||
var bbcodeMap = { b: 'strong', u: 'u', i: 'em', color: 'span', size: 'span', left: 'div', right: 'div', center: 'div', justify: 'div', quote: 'blockquote', code: 'code', url: 'a', email: 'span', img: 'span', '*': 'li', list: 'ol' },
|
||||
convertMap = { strong: 'b', b: 'b', u: 'u', em: 'i', i: 'i', code: 'code', li: '*' },
|
||||
tagnameMap = { strong: 'b', em: 'i', u: 'u', li: '*', ul: 'list', ol: 'list', code: 'code', a: 'link', img: 'img', blockquote: 'quote' },
|
||||
stylesMap = { color: 'color', size: 'font-size', left: 'text-align', center: 'text-align', right: 'text-align', justify: 'text-align' },
|
||||
attributesMap = { url: 'href', email: 'mailhref', quote: 'cite', list: 'listType' };
|
||||
|
||||
// List of block-like tags.
|
||||
var dtd = CKEDITOR.dtd,
|
||||
blockLikeTags = CKEDITOR.tools.extend( { table: 1 }, dtd.$block, dtd.$listItem, dtd.$tableContent, dtd.$list );
|
||||
|
||||
var semicolonFixRegex = /\s*(?:;\s*|$)/;
|
||||
|
||||
function serializeStyleText( stylesObject ) {
|
||||
var styleText = '';
|
||||
for ( var style in stylesObject ) {
|
||||
var styleVal = stylesObject[ style ],
|
||||
text = ( style + ':' + styleVal ).replace( semicolonFixRegex, ';' );
|
||||
|
||||
styleText += text;
|
||||
}
|
||||
return styleText;
|
||||
}
|
||||
|
||||
// Maintain the map of smiley-to-description.
|
||||
// jscs:disable maximumLineLength
|
||||
var smileyMap = { smiley: ':)', sad: ':(', wink: ';)', laugh: ':D', cheeky: ':P', blush: ':*)', surprise: ':-o', indecision: ':|', angry: '>:(', angel: 'o:)', cool: '8-)', devil: '>:-)', crying: ';(', kiss: ':-*' },
|
||||
// jscs:enable maximumLineLength
|
||||
smileyReverseMap = {},
|
||||
smileyRegExp = [];
|
||||
|
||||
// Build regexp for the list of smiley text.
|
||||
for ( var i in smileyMap ) {
|
||||
smileyReverseMap[ smileyMap[ i ] ] = i;
|
||||
smileyRegExp.push( smileyMap[ i ].replace( /\(|\)|\:|\/|\*|\-|\|/g, function( match ) {
|
||||
return '\\' + match;
|
||||
} ) );
|
||||
}
|
||||
|
||||
smileyRegExp = new RegExp( smileyRegExp.join( '|' ), 'g' );
|
||||
|
||||
var decodeHtml = ( function() {
|
||||
var regex = [],
|
||||
entities = {
|
||||
nbsp: '\u00A0', // IE | FF
|
||||
shy: '\u00AD' // IE
|
||||
};
|
||||
|
||||
for ( var entity in entities )
|
||||
regex.push( entity );
|
||||
|
||||
regex = new RegExp( '&(' + regex.join( '|' ) + ');', 'g' );
|
||||
|
||||
return function( html ) {
|
||||
return html.replace( regex, function( match, entity ) {
|
||||
return entities[ entity ];
|
||||
} );
|
||||
};
|
||||
} )();
|
||||
|
||||
CKEDITOR.BBCodeParser = function() {
|
||||
this._ = {
|
||||
bbcPartsRegex: /(?:\[([^\/\]=]*?)(?:=([^\]]*?))?\])|(?:\[\/([a-z]{1,16})\])/ig
|
||||
};
|
||||
};
|
||||
|
||||
CKEDITOR.BBCodeParser.prototype = {
|
||||
parse: function( bbcode ) {
|
||||
var parts, part,
|
||||
lastIndex = 0;
|
||||
|
||||
while ( ( parts = this._.bbcPartsRegex.exec( bbcode ) ) ) {
|
||||
var tagIndex = parts.index;
|
||||
if ( tagIndex > lastIndex ) {
|
||||
var text = bbcode.substring( lastIndex, tagIndex );
|
||||
this.onText( text, 1 );
|
||||
}
|
||||
|
||||
lastIndex = this._.bbcPartsRegex.lastIndex;
|
||||
|
||||
// "parts" is an array with the following items:
|
||||
// 0 : The entire match for opening/closing tags and line-break;
|
||||
// 1 : line-break;
|
||||
// 2 : open of tag excludes option;
|
||||
// 3 : tag option;
|
||||
// 4 : close of tag;
|
||||
|
||||
part = ( parts[ 1 ] || parts[ 3 ] || '' ).toLowerCase();
|
||||
// Unrecognized tags should be delivered as a simple text (https://dev.ckeditor.com/ticket/7860).
|
||||
if ( part && !bbcodeMap[ part ] ) {
|
||||
this.onText( parts[ 0 ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Opening tag
|
||||
if ( parts[ 1 ] ) {
|
||||
var tagName = bbcodeMap[ part ],
|
||||
attribs = {},
|
||||
styles = {},
|
||||
optionPart = parts[ 2 ];
|
||||
|
||||
// Special handling of justify tags, these provide the alignment as a tag name (#2248).
|
||||
if ( part == 'left' || part == 'right' || part == 'center' || part == 'justify' ) {
|
||||
optionPart = part;
|
||||
}
|
||||
|
||||
if ( optionPart ) {
|
||||
if ( part == 'list' ) {
|
||||
if ( !isNaN( optionPart ) )
|
||||
optionPart = 'decimal';
|
||||
else if ( /^[a-z]+$/.test( optionPart ) )
|
||||
optionPart = 'lower-alpha';
|
||||
else if ( /^[A-Z]+$/.test( optionPart ) )
|
||||
optionPart = 'upper-alpha';
|
||||
}
|
||||
|
||||
if ( stylesMap[ part ] ) {
|
||||
// Font size represents percentage.
|
||||
if ( part == 'size' ) {
|
||||
optionPart += '%';
|
||||
}
|
||||
|
||||
styles[ stylesMap[ part ] ] = optionPart;
|
||||
attribs.style = serializeStyleText( styles );
|
||||
} else if ( attributesMap[ part ] ) {
|
||||
// All the input BBCode is encoded at the beginning so <> characters in the textual part
|
||||
// are later correctly preserved in HTML. However... it affects parts that now become
|
||||
// attributes, so we need to revert that. As a matter of fact, the content should not be
|
||||
// encoded at the beginning, but only later when creating text nodes (encoding should be more precise)
|
||||
// but it's too late not for such changes.
|
||||
attribs[ attributesMap[ part ] ] = CKEDITOR.tools.htmlDecode( optionPart );
|
||||
}
|
||||
}
|
||||
|
||||
// Two special handling - image and email, protect them
|
||||
// as "span" with an attribute marker.
|
||||
if ( part == 'email' || part == 'img' )
|
||||
attribs.bbcode = part;
|
||||
|
||||
this.onTagOpen( tagName, attribs, CKEDITOR.dtd.$empty[ tagName ] );
|
||||
}
|
||||
// Closing tag
|
||||
else if ( parts[ 3 ] ) {
|
||||
this.onTagClose( bbcodeMap[part] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( bbcode.length > lastIndex )
|
||||
this.onText( bbcode.substring( lastIndex, bbcode.length ), 1 );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string.
|
||||
*
|
||||
* var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<b>Sample</b> Text' );
|
||||
* alert( fragment.children[ 0 ].name ); // 'b'
|
||||
* alert( fragment.children[ 1 ].value ); // ' Text'
|
||||
*
|
||||
* @static
|
||||
* @member CKEDITOR.htmlParser.fragment
|
||||
* @param {String} source The HTML to be parsed, filling the fragment.
|
||||
* @returns {CKEDITOR.htmlParser.fragment} The fragment created.
|
||||
*/
|
||||
CKEDITOR.htmlParser.fragment.fromBBCode = function( source ) {
|
||||
var parser = new CKEDITOR.BBCodeParser(),
|
||||
fragment = new CKEDITOR.htmlParser.fragment(),
|
||||
pendingInline = [],
|
||||
pendingBrs = 0,
|
||||
currentNode = fragment,
|
||||
returnPoint;
|
||||
|
||||
function checkPending( newTagName ) {
|
||||
if ( pendingInline.length > 0 ) {
|
||||
for ( var i = 0; i < pendingInline.length; i++ ) {
|
||||
var pendingElement = pendingInline[ i ],
|
||||
pendingName = pendingElement.name,
|
||||
pendingDtd = CKEDITOR.dtd[ pendingName ],
|
||||
currentDtd = currentNode.name && CKEDITOR.dtd[ currentNode.name ];
|
||||
|
||||
if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] || !CKEDITOR.dtd[ newTagName ] ) ) {
|
||||
// Get a clone for the pending element.
|
||||
pendingElement = pendingElement.clone();
|
||||
|
||||
// Add it to the current node and make it the current,
|
||||
// so the new element will be added inside of it.
|
||||
pendingElement.parent = currentNode;
|
||||
currentNode = pendingElement;
|
||||
|
||||
// Remove the pending element (back the index by one
|
||||
// to properly process the next entry).
|
||||
pendingInline.splice( i, 1 );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkPendingBrs( tagName, closing ) {
|
||||
var len = currentNode.children.length,
|
||||
previous = len > 0 && currentNode.children[ len - 1 ],
|
||||
lineBreakParent = !previous && writer.getRule( tagnameMap[ currentNode.name ], 'breakAfterOpen' ),
|
||||
lineBreakPrevious = previous && previous.type == CKEDITOR.NODE_ELEMENT && writer.getRule( tagnameMap[ previous.name ], 'breakAfterClose' ),
|
||||
lineBreakCurrent = tagName && writer.getRule( tagnameMap[ tagName ], closing ? 'breakBeforeClose' : 'breakBeforeOpen' );
|
||||
|
||||
if ( pendingBrs && ( lineBreakParent || lineBreakPrevious || lineBreakCurrent ) )
|
||||
pendingBrs--;
|
||||
|
||||
// 1. Either we're at the end of block, where it requires us to compensate the br filler
|
||||
// removing logic (from htmldataprocessor).
|
||||
// 2. Or we're at the end of pseudo block, where it requires us to compensate
|
||||
// the bogus br effect.
|
||||
if ( pendingBrs && tagName in blockLikeTags )
|
||||
pendingBrs++;
|
||||
|
||||
while ( pendingBrs && pendingBrs-- )
|
||||
currentNode.children.push( previous = new CKEDITOR.htmlParser.element( 'br' ) );
|
||||
}
|
||||
|
||||
function addElement( node, target ) {
|
||||
checkPendingBrs( node.name, 1 );
|
||||
|
||||
target = target || currentNode || fragment;
|
||||
|
||||
var len = target.children.length,
|
||||
previous = len > 0 && target.children[ len - 1 ] || null;
|
||||
|
||||
node.previous = previous;
|
||||
node.parent = target;
|
||||
|
||||
target.children.push( node );
|
||||
|
||||
if ( node.returnPoint ) {
|
||||
currentNode = node.returnPoint;
|
||||
delete node.returnPoint;
|
||||
}
|
||||
}
|
||||
|
||||
parser.onTagOpen = function( tagName, attributes ) {
|
||||
var element = new CKEDITOR.htmlParser.element( tagName, attributes );
|
||||
|
||||
// This is a tag to be removed if empty, so do not add it immediately.
|
||||
if ( CKEDITOR.dtd.$removeEmpty[ tagName ] ) {
|
||||
pendingInline.push( element );
|
||||
return;
|
||||
}
|
||||
|
||||
var currentName = currentNode.name;
|
||||
|
||||
var currentDtd = currentName && ( CKEDITOR.dtd[ currentName ] || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) );
|
||||
|
||||
// If the element cannot be child of the current element.
|
||||
if ( currentDtd && !currentDtd[ tagName ] ) {
|
||||
var reApply = false,
|
||||
addPoint; // New position to start adding nodes.
|
||||
|
||||
// If the element name is the same as the current element name,
|
||||
// then just close the current one and append the new one to the
|
||||
// parent. This situation usually happens with <p>, <li>, <dt> and
|
||||
// <dd>, specially in IE. Do not enter in this if block in this case.
|
||||
if ( tagName == currentName )
|
||||
addElement( currentNode, currentNode.parent );
|
||||
else if ( tagName in CKEDITOR.dtd.$listItem ) {
|
||||
parser.onTagOpen( 'ul', {} );
|
||||
addPoint = currentNode;
|
||||
reApply = true;
|
||||
} else {
|
||||
addElement( currentNode, currentNode.parent );
|
||||
|
||||
// The current element is an inline element, which
|
||||
// cannot hold the new one. Put it in the pending list,
|
||||
// and try adding the new one after it.
|
||||
pendingInline.unshift( currentNode );
|
||||
reApply = true;
|
||||
}
|
||||
|
||||
if ( addPoint )
|
||||
currentNode = addPoint;
|
||||
// Try adding it to the return point, or the parent element.
|
||||
else
|
||||
currentNode = currentNode.returnPoint || currentNode.parent;
|
||||
|
||||
if ( reApply ) {
|
||||
parser.onTagOpen.apply( this, arguments );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
checkPending( tagName );
|
||||
checkPendingBrs( tagName );
|
||||
|
||||
element.parent = currentNode;
|
||||
element.returnPoint = returnPoint;
|
||||
returnPoint = 0;
|
||||
|
||||
if ( element.isEmpty )
|
||||
addElement( element );
|
||||
else
|
||||
currentNode = element;
|
||||
};
|
||||
|
||||
parser.onTagClose = function( tagName ) {
|
||||
// Check if there is any pending tag to be closed.
|
||||
for ( var i = pendingInline.length - 1; i >= 0; i-- ) {
|
||||
// If found, just remove it from the list.
|
||||
if ( tagName == pendingInline[ i ].name ) {
|
||||
pendingInline.splice( i, 1 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var pendingAdd = [],
|
||||
newPendingInline = [],
|
||||
candidate = currentNode;
|
||||
|
||||
while ( candidate.type && candidate.name != tagName ) {
|
||||
// If this is an inline element, add it to the pending list, if we're
|
||||
// really closing one of the parents element later, they will continue
|
||||
// after it.
|
||||
if ( !candidate._.isBlockLike )
|
||||
newPendingInline.unshift( candidate );
|
||||
|
||||
// This node should be added to it's parent at this point. But,
|
||||
// it should happen only if the closing tag is really closing
|
||||
// one of the nodes. So, for now, we just cache it.
|
||||
pendingAdd.push( candidate );
|
||||
|
||||
candidate = candidate.parent;
|
||||
}
|
||||
|
||||
if ( candidate.type ) {
|
||||
// Add all elements that have been found in the above loop.
|
||||
for ( i = 0; i < pendingAdd.length; i++ ) {
|
||||
var node = pendingAdd[ i ];
|
||||
addElement( node, node.parent );
|
||||
}
|
||||
|
||||
currentNode = candidate;
|
||||
|
||||
|
||||
addElement( candidate, candidate.parent );
|
||||
|
||||
// The parent should start receiving new nodes now, except if
|
||||
// addElement changed the currentNode.
|
||||
if ( candidate == currentNode )
|
||||
currentNode = currentNode.parent;
|
||||
|
||||
pendingInline = pendingInline.concat( newPendingInline );
|
||||
}
|
||||
};
|
||||
|
||||
parser.onText = function( text ) {
|
||||
var currentDtd = CKEDITOR.dtd[ currentNode.name ];
|
||||
if ( !currentDtd || currentDtd[ '#' ] ) {
|
||||
checkPendingBrs();
|
||||
checkPending();
|
||||
|
||||
text.replace( /(\r\n|[\r\n])|[^\r\n]*/g, function( piece, lineBreak ) {
|
||||
if ( lineBreak !== undefined && lineBreak.length )
|
||||
pendingBrs++;
|
||||
else if ( piece.length ) {
|
||||
var lastIndex = 0;
|
||||
|
||||
// Create smiley from text emotion.
|
||||
piece.replace( smileyRegExp, function( match, index ) {
|
||||
addElement( new CKEDITOR.htmlParser.text( piece.substring( lastIndex, index ) ), currentNode );
|
||||
addElement( new CKEDITOR.htmlParser.element( 'smiley', { desc: smileyReverseMap[ match ] } ), currentNode );
|
||||
lastIndex = index + match.length;
|
||||
} );
|
||||
|
||||
if ( lastIndex != piece.length )
|
||||
addElement( new CKEDITOR.htmlParser.text( piece.substring( lastIndex, piece.length ) ), currentNode );
|
||||
}
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
// Parse it.
|
||||
parser.parse( CKEDITOR.tools.htmlEncode( source ) );
|
||||
|
||||
// Close all hanging nodes.
|
||||
while ( currentNode.type != CKEDITOR.NODE_DOCUMENT_FRAGMENT ) {
|
||||
var parent = currentNode.parent,
|
||||
node = currentNode;
|
||||
|
||||
addElement( node, parent );
|
||||
currentNode = parent;
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
var BBCodeWriter = CKEDITOR.tools.createClass( {
|
||||
$: function() {
|
||||
this._ = {
|
||||
output: [],
|
||||
rules: []
|
||||
};
|
||||
|
||||
// List and list item.
|
||||
this.setRules( 'list', { breakBeforeOpen: 1, breakAfterOpen: 1, breakBeforeClose: 1, breakAfterClose: 1 } );
|
||||
|
||||
this.setRules( '*', {
|
||||
breakBeforeOpen: 1,
|
||||
breakAfterOpen: 0,
|
||||
breakBeforeClose: 1,
|
||||
breakAfterClose: 0
|
||||
} );
|
||||
|
||||
this.setRules( 'quote', {
|
||||
breakBeforeOpen: 1,
|
||||
breakAfterOpen: 0,
|
||||
breakBeforeClose: 0,
|
||||
breakAfterClose: 1
|
||||
} );
|
||||
},
|
||||
|
||||
proto: {
|
||||
//
|
||||
// Sets formatting rules for a given tag. The possible rules are:
|
||||
// <ul>
|
||||
// <li><b>breakBeforeOpen</b>: break line before the opener tag for this element.</li>
|
||||
// <li><b>breakAfterOpen</b>: break line after the opener tag for this element.</li>
|
||||
// <li><b>breakBeforeClose</b>: break line before the closer tag for this element.</li>
|
||||
// <li><b>breakAfterClose</b>: break line after the closer tag for this element.</li>
|
||||
// </ul>
|
||||
//
|
||||
// All rules default to "false". Each call to the function overrides
|
||||
// already present rules, leaving the undefined untouched.
|
||||
//
|
||||
// @param {String} tagName The tag name to which set the rules.
|
||||
// @param {Object} rules An object containing the element rules.
|
||||
// @example
|
||||
// // Break line before and after "img" tags.
|
||||
// writer.setRules( 'list',
|
||||
// {
|
||||
// breakBeforeOpen : true
|
||||
// breakAfterOpen : true
|
||||
// });
|
||||
setRules: function( tagName, rules ) {
|
||||
var currentRules = this._.rules[ tagName ];
|
||||
|
||||
if ( currentRules )
|
||||
CKEDITOR.tools.extend( currentRules, rules, true );
|
||||
else
|
||||
this._.rules[ tagName ] = rules;
|
||||
},
|
||||
|
||||
getRule: function( tagName, ruleName ) {
|
||||
return this._.rules[ tagName ] && this._.rules[ tagName ][ ruleName ];
|
||||
},
|
||||
|
||||
openTag: function( tag ) {
|
||||
if ( tag in bbcodeMap ) {
|
||||
if ( this.getRule( tag, 'breakBeforeOpen' ) )
|
||||
this.lineBreak( 1 );
|
||||
|
||||
this.write( '[', tag );
|
||||
}
|
||||
},
|
||||
|
||||
openTagClose: function( tag ) {
|
||||
if ( tag == 'br' )
|
||||
this._.output.push( '\n' );
|
||||
else if ( tag in bbcodeMap ) {
|
||||
this.write( ']' );
|
||||
if ( this.getRule( tag, 'breakAfterOpen' ) )
|
||||
this.lineBreak( 1 );
|
||||
}
|
||||
},
|
||||
|
||||
attribute: function( name, val ) {
|
||||
if ( name == 'option' ) {
|
||||
this.write( '=', val );
|
||||
}
|
||||
},
|
||||
|
||||
closeTag: function( tag ) {
|
||||
if ( tag in bbcodeMap ) {
|
||||
if ( this.getRule( tag, 'breakBeforeClose' ) )
|
||||
this.lineBreak( 1 );
|
||||
|
||||
tag != '*' && this.write( '[/', tag, ']' );
|
||||
|
||||
if ( this.getRule( tag, 'breakAfterClose' ) )
|
||||
this.lineBreak( 1 );
|
||||
}
|
||||
},
|
||||
|
||||
text: function( text ) {
|
||||
this.write( text );
|
||||
},
|
||||
|
||||
comment: function() {},
|
||||
|
||||
// Output line-break for formatting.
|
||||
lineBreak: function() {
|
||||
// Avoid line break when:
|
||||
// 1) Previous tag already put one.
|
||||
// 2) We're at output start.
|
||||
if ( !this._.hasLineBreak && this._.output.length ) {
|
||||
this.write( '\n' );
|
||||
this._.hasLineBreak = 1;
|
||||
}
|
||||
},
|
||||
|
||||
write: function() {
|
||||
this._.hasLineBreak = 0;
|
||||
var data = Array.prototype.join.call( arguments, '' );
|
||||
this._.output.push( data );
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this._.output = [];
|
||||
this._.hasLineBreak = 0;
|
||||
},
|
||||
|
||||
getHtml: function( reset ) {
|
||||
var bbcode = this._.output.join( '' );
|
||||
|
||||
if ( reset )
|
||||
this.reset();
|
||||
|
||||
return decodeHtml( bbcode );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
var writer = new BBCodeWriter();
|
||||
|
||||
CKEDITOR.plugins.add( 'bbcode', {
|
||||
requires: 'entities',
|
||||
|
||||
// Adapt some critical editor configuration for better support
|
||||
// of BBCode environment.
|
||||
beforeInit: function( editor ) {
|
||||
var config = editor.config;
|
||||
|
||||
CKEDITOR.tools.extend( config, {
|
||||
// This one is for backwards compatibility only as
|
||||
// editor#enterMode is already set at this stage (https://dev.ckeditor.com/ticket/11202).
|
||||
enterMode: CKEDITOR.ENTER_BR,
|
||||
basicEntities: false,
|
||||
entities: false,
|
||||
fillEmptyBlocks: false
|
||||
}, true );
|
||||
|
||||
editor.filter.disable();
|
||||
|
||||
// Since CKEditor 4.3.0, editor#(active)enterMode is set before
|
||||
// beforeInit. Properties got to be updated (https://dev.ckeditor.com/ticket/11202).
|
||||
editor.activeEnterMode = editor.enterMode = CKEDITOR.ENTER_BR;
|
||||
},
|
||||
|
||||
init: function( editor ) {
|
||||
var config = editor.config;
|
||||
|
||||
function BBCodeToHtml( code ) {
|
||||
var fragment = CKEDITOR.htmlParser.fragment.fromBBCode( code ),
|
||||
writer = new CKEDITOR.htmlParser.basicWriter();
|
||||
|
||||
fragment.writeHtml( writer, bbcodeFilter );
|
||||
return writer.getHtml( true );
|
||||
}
|
||||
|
||||
var bbcodeFilter = new CKEDITOR.htmlParser.filter();
|
||||
bbcodeFilter.addRules( {
|
||||
elements: {
|
||||
blockquote: function( element ) {
|
||||
var quoted = new CKEDITOR.htmlParser.element( 'div' );
|
||||
quoted.children = element.children;
|
||||
element.children = [ quoted ];
|
||||
var citeText = element.attributes.cite;
|
||||
if ( citeText ) {
|
||||
var cite = new CKEDITOR.htmlParser.element( 'cite' );
|
||||
cite.add( new CKEDITOR.htmlParser.text( citeText.replace( /^"|"$/g, '' ) ) );
|
||||
delete element.attributes.cite;
|
||||
element.children.unshift( cite );
|
||||
}
|
||||
},
|
||||
span: function( element ) {
|
||||
var bbcode;
|
||||
if ( ( bbcode = element.attributes.bbcode ) ) {
|
||||
if ( bbcode == 'img' ) {
|
||||
element.name = 'img';
|
||||
element.attributes.src = element.children[ 0 ].value;
|
||||
element.children = [];
|
||||
} else if ( bbcode == 'email' ) {
|
||||
element.name = 'a';
|
||||
element.attributes.href = 'mailto:' + element.children[ 0 ].value;
|
||||
}
|
||||
|
||||
delete element.attributes.bbcode;
|
||||
}
|
||||
},
|
||||
ol: function( element ) {
|
||||
if ( element.attributes.listType ) {
|
||||
if ( element.attributes.listType != 'decimal' )
|
||||
element.attributes.style = 'list-style-type:' + element.attributes.listType;
|
||||
} else {
|
||||
element.name = 'ul';
|
||||
}
|
||||
|
||||
delete element.attributes.listType;
|
||||
},
|
||||
a: function( element ) {
|
||||
if ( !element.attributes.href )
|
||||
element.attributes.href = element.children[ 0 ].value;
|
||||
},
|
||||
smiley: function( element ) {
|
||||
element.name = 'img';
|
||||
|
||||
var description = element.attributes.desc,
|
||||
image = config.smiley_images[ CKEDITOR.tools.indexOf( config.smiley_descriptions, description ) ],
|
||||
src = CKEDITOR.tools.htmlEncode( config.smiley_path + image );
|
||||
|
||||
element.attributes = {
|
||||
src: src,
|
||||
'data-cke-saved-src': src,
|
||||
title: description,
|
||||
alt: description
|
||||
};
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
editor.dataProcessor.htmlFilter.addRules( {
|
||||
elements: {
|
||||
$: function( element ) {
|
||||
var attributes = element.attributes,
|
||||
style = CKEDITOR.tools.parseCssText( attributes.style, 1 ),
|
||||
value;
|
||||
|
||||
var tagName = element.name;
|
||||
if ( tagName in convertMap )
|
||||
tagName = convertMap[ tagName ];
|
||||
else if ( tagName == 'span' ) {
|
||||
if ( ( value = style.color ) ) {
|
||||
tagName = 'color';
|
||||
value = CKEDITOR.tools.convertRgbToHex( value );
|
||||
} else if ( ( value = style[ 'font-size' ] ) ) {
|
||||
var percentValue = value.match( /(\d+)%$/ );
|
||||
if ( percentValue ) {
|
||||
value = percentValue[ 1 ];
|
||||
tagName = 'size';
|
||||
}
|
||||
}
|
||||
} else if ( tagName == 'ol' || tagName == 'ul' ) {
|
||||
if ( ( value = style[ 'list-style-type' ] ) ) {
|
||||
switch ( value ) {
|
||||
case 'lower-alpha':
|
||||
value = 'a';
|
||||
break;
|
||||
case 'upper-alpha':
|
||||
value = 'A';
|
||||
break;
|
||||
}
|
||||
} else if ( tagName == 'ol' ) {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
tagName = 'list';
|
||||
} else if ( tagName == 'blockquote' ) {
|
||||
try {
|
||||
var cite = element.children[ 0 ],
|
||||
quoted = element.children[ 1 ],
|
||||
citeText = cite.name == 'cite' && cite.children[ 0 ].value;
|
||||
|
||||
if ( citeText ) {
|
||||
value = '"' + citeText + '"';
|
||||
element.children = quoted.children;
|
||||
}
|
||||
|
||||
} catch ( er ) {}
|
||||
|
||||
tagName = 'quote';
|
||||
} else if ( tagName == 'a' ) {
|
||||
if ( ( value = attributes.href ) ) {
|
||||
if ( value.indexOf( 'mailto:' ) !== -1 ) {
|
||||
tagName = 'email';
|
||||
// [email] should have a single text child with email address.
|
||||
element.children = [ new CKEDITOR.htmlParser.text( value.replace( 'mailto:', '' ) ) ];
|
||||
value = '';
|
||||
} else {
|
||||
var singleton = element.children.length == 1 && element.children[ 0 ];
|
||||
if ( singleton && singleton.type == CKEDITOR.NODE_TEXT && singleton.value == value )
|
||||
value = '';
|
||||
|
||||
tagName = 'url';
|
||||
}
|
||||
}
|
||||
} else if ( tagName == 'img' ) {
|
||||
element.isEmpty = 0;
|
||||
|
||||
// Translate smiley (image) to text emotion.
|
||||
var src = attributes[ 'data-cke-saved-src' ] || attributes.src,
|
||||
alt = attributes.alt;
|
||||
|
||||
if ( src && src.indexOf( editor.config.smiley_path ) != -1 && alt )
|
||||
return new CKEDITOR.htmlParser.text( smileyMap[ alt ] );
|
||||
else
|
||||
element.children = [ new CKEDITOR.htmlParser.text( src ) ];
|
||||
}
|
||||
|
||||
element.name = tagName;
|
||||
value && ( element.attributes.option = value );
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
div: function( element ) {
|
||||
var alignment = CKEDITOR.tools.parseCssText( element.attributes.style, 1 )[ 'text-align' ] || '';
|
||||
|
||||
if ( alignment ) {
|
||||
element.name = alignment;
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
// Remove any bogus br from the end of a pseudo block,
|
||||
// e.g. <div>some text<br /><p>paragraph</p></div>
|
||||
br: function( element ) {
|
||||
var next = element.next;
|
||||
if ( next && next.name in blockLikeTags )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, 1 );
|
||||
|
||||
editor.dataProcessor.writer = writer;
|
||||
|
||||
function onSetData( evt ) {
|
||||
var bbcode = evt.data.dataValue;
|
||||
evt.data.dataValue = BBCodeToHtml( bbcode );
|
||||
}
|
||||
|
||||
// Skip the first "setData" call from inline creator, to allow content of
|
||||
// HTML to be loaded from the page element.
|
||||
if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_INLINE )
|
||||
editor.once( 'contentDom', function() {
|
||||
editor.on( 'setData', onSetData );
|
||||
} );
|
||||
else
|
||||
editor.on( 'setData', onSetData );
|
||||
|
||||
},
|
||||
|
||||
afterInit: function( editor ) {
|
||||
var filters;
|
||||
if ( editor._.elementsPath ) {
|
||||
// Eliminate irrelevant elements from displaying, e.g body and p.
|
||||
if ( ( filters = editor._.elementsPath.filters ) ) {
|
||||
filters.push( function( element ) {
|
||||
var htmlName = element.getName(),
|
||||
name = tagnameMap[ htmlName ] || false;
|
||||
|
||||
// Specialized anchor presents as email.
|
||||
if ( name == 'link' && element.getAttribute( 'href' ).indexOf( 'mailto:' ) === 0 )
|
||||
name = 'email';
|
||||
// Styled span could be either size or color.
|
||||
else if ( htmlName == 'span' ) {
|
||||
if ( element.getStyle( 'font-size' ) )
|
||||
name = 'size';
|
||||
else if ( element.getStyle( 'color' ) )
|
||||
name = 'color';
|
||||
// Styled div could be align
|
||||
} else if ( htmlName == 'div' && element.getStyle( 'text-align' ) ) {
|
||||
name = element.getStyle( 'text-align' );
|
||||
} else if ( name == 'img' ) {
|
||||
var src = element.data( 'cke-saved-src' ) || element.getAttribute( 'src' );
|
||||
if ( src && src.indexOf( editor.config.smiley_path ) === 0 )
|
||||
name = 'smiley';
|
||||
}
|
||||
|
||||
return name;
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
} )();
|
|
@ -1,114 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BBCode Plugin — CKEditor Sample</title>
|
||||
<script src="../../../ckeditor.js"></script>
|
||||
<script src="../../../samples/old/sample.js"></script>
|
||||
<link rel="stylesheet" href="../../../samples/old/sample.css">
|
||||
<meta name="ckeditor-sample-required-plugins" content="sourcearea">
|
||||
<meta name="ckeditor-sample-name" content="Output for BBCode">
|
||||
<meta name="ckeditor-sample-group" content="Additional Plugins">
|
||||
<meta name="ckeditor-sample-description" content="Configuring CKEditor to produce BBCode tags instead of HTML.">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="samples">
|
||||
<a href="../../../samples/old/index.html">CKEditor Samples</a> » BBCode Plugin
|
||||
</h1>
|
||||
<div class="warning deprecated">
|
||||
This sample is not maintained anymore. Check out its <a href="https://ckeditor.com/docs/ckeditor4/latest/examples/bbcode.html">brand new version in CKEditor Examples</a>.
|
||||
</div>
|
||||
<div class="description">
|
||||
<p>
|
||||
This sample shows how to configure CKEditor to output <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a> format instead of HTML.
|
||||
Please note that the editor configuration was modified to reflect what is needed in a BBCode editing environment.
|
||||
Smiley images, for example, were stripped to the emoticons that are commonly used in some BBCode dialects.
|
||||
</p>
|
||||
<p>
|
||||
Please note that currently there is no standard for the BBCode markup language, so its implementation
|
||||
for different platforms (message boards, blogs etc.) can vary. This means that before using CKEditor to
|
||||
output BBCode you may need to adjust the implementation to your own environment.
|
||||
</p>
|
||||
<p>
|
||||
A snippet of the configuration code can be seen below; check the source of this page for
|
||||
a full definition:
|
||||
</p>
|
||||
<pre class="samples">
|
||||
CKEDITOR.replace( 'editor1', {
|
||||
<strong>extraPlugins: 'bbcode',</strong>
|
||||
toolbar: [
|
||||
[ 'Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo' ],
|
||||
[ 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat' ],
|
||||
[ 'Link', 'Unlink', 'Image' ],
|
||||
'/',
|
||||
[ 'FontSize', 'Bold', 'Italic', 'Underline' ],
|
||||
[ 'NumberedList', 'BulletedList', '-', 'Blockquote' ],
|
||||
[ 'TextColor', '-', 'Smiley', 'SpecialChar', '-', 'Maximize' ]
|
||||
],
|
||||
... <i>some other configurations omitted here</i>
|
||||
}); </pre>
|
||||
</div>
|
||||
<form action="../../../samples/sample_posteddata.php" method="post">
|
||||
<p>
|
||||
<label for="editor1">
|
||||
Editor 1:
|
||||
</label>
|
||||
<textarea cols="80" id="editor1" name="editor1" rows="10">This is some [b]sample text[/b]. You are using [url=https://ckeditor.com/]CKEditor[/url].</textarea>
|
||||
<script>
|
||||
|
||||
// Replace the <textarea id="editor"> with an CKEditor
|
||||
// instance, using the "bbcode" plugin, shaping some of the
|
||||
// editor configuration to fit BBCode environment.
|
||||
CKEDITOR.replace( 'editor1', {
|
||||
extraPlugins: 'bbcode',
|
||||
// Remove unused plugins.
|
||||
removePlugins: 'bidi,dialogadvtab,div,filebrowser,flash,format,forms,horizontalrule,iframe,justify,liststyle,pagebreak,showborders,stylescombo,table,tabletools,templates',
|
||||
// Width and height are not supported in the BBCode format, so object resizing is disabled.
|
||||
disableObjectResizing: true,
|
||||
// Define font sizes in percent values.
|
||||
fontSize_sizes: "30/30%;50/50%;100/100%;120/120%;150/150%;200/200%;300/300%",
|
||||
toolbar: [
|
||||
[ 'Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo' ],
|
||||
[ 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat' ],
|
||||
[ 'Link', 'Unlink', 'Image', 'Smiley', 'SpecialChar' ],
|
||||
'/',
|
||||
[ 'Bold', 'Italic', 'Underline' ],
|
||||
[ 'FontSize' ],
|
||||
[ 'TextColor' ],
|
||||
[ 'NumberedList', 'BulletedList', '-', 'Blockquote' ],
|
||||
[ 'Maximize' ]
|
||||
],
|
||||
// Strip CKEditor smileys to those commonly used in BBCode.
|
||||
smiley_images: [
|
||||
'regular_smile.png', 'sad_smile.png', 'wink_smile.png', 'teeth_smile.png', 'tongue_smile.png',
|
||||
'embarrassed_smile.png', 'omg_smile.png', 'whatchutalkingabout_smile.png', 'angel_smile.png',
|
||||
'shades_smile.png', 'cry_smile.png', 'kiss.png'
|
||||
],
|
||||
smiley_descriptions: [
|
||||
'smiley', 'sad', 'wink', 'laugh', 'cheeky', 'blush', 'surprise',
|
||||
'indecision', 'angel', 'cool', 'crying', 'kiss'
|
||||
]
|
||||
});
|
||||
|
||||
</script>
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" value="Submit">
|
||||
</p>
|
||||
</form>
|
||||
<div id="footer">
|
||||
<hr>
|
||||
<p>
|
||||
CKEditor - The text editor for the Internet - <a class="samples" href="https://ckeditor.com/">https://ckeditor.com</a>
|
||||
</p>
|
||||
<p id="copy">
|
||||
Copyright © 2003-2019, <a class="samples" href="https://cksource.com/">CKSource</a> - Frederico
|
||||
Knabben. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,168 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BBCode plugin playground – CKEditor Sample</title>
|
||||
<script src="../../../ckeditor.js"></script>
|
||||
<link href="../../../samples/old/sample.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#editables
|
||||
{
|
||||
float:left;
|
||||
width: 49%
|
||||
}
|
||||
|
||||
#preview
|
||||
{
|
||||
width: 50%;
|
||||
float:right;
|
||||
}
|
||||
|
||||
#console
|
||||
{
|
||||
height: 300px;
|
||||
padding: 5px 10px;
|
||||
border: solid 3px #555;
|
||||
overflow: auto;
|
||||
color: #000;
|
||||
transition: border-color 0.5s;
|
||||
font-family: Monaco, monospace;
|
||||
font-size: 13px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
#console.updated {
|
||||
border-color: #0B0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="samples">
|
||||
CKEditor Sample — BBCode plugin playground
|
||||
</h1>
|
||||
<div id="main">
|
||||
<div class="description">
|
||||
<p>
|
||||
This sample shows how to configure CKEditor to output <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a> format instead of HTML.
|
||||
Please note that the editor configuration was modified to reflect what is needed in a BBCode editing environment.
|
||||
Smiley images, for example, were stripped to the emoticons that are commonly used in some BBCode dialects.
|
||||
</p>
|
||||
<p>
|
||||
Please note that currently there is no standard for the BBCode markup language, so its implementation
|
||||
for different platforms (message boards, blogs etc.) can vary. This means that before using CKEditor to
|
||||
output BBCode you may need to adjust the implementation to your own environment.
|
||||
</p>
|
||||
<p>
|
||||
A snippet of the configuration code can be seen below; check the source of this page for
|
||||
a full definition:
|
||||
</p>
|
||||
<pre class="samples">
|
||||
CKEDITOR.inline( 'editor1', {
|
||||
<strong>extraPlugins : 'bbcode',</strong>
|
||||
<i>(below configurations details omitted:)</i>
|
||||
toolbar : ...,
|
||||
fontSize_sizes : ...,
|
||||
smiley_images : ...,
|
||||
smiley_descriptions : ...
|
||||
});</pre>
|
||||
</div>
|
||||
|
||||
<div id="editables">
|
||||
<textarea id="editor1">
|
||||
[img]http://a.cksource.com/f/1/img/logo-ckeditor.gif[/img]
|
||||
"[b]Little Red Riding Hood[/b]" is a famous [url=http://en.wikipedia.org/wiki/Fairy_tale]fairy tale[/url] about a young girl's encounter with a wolf. The story has been changed considerably in its history and subject to numerous modern adaptations and readings.
|
||||
[list]
|
||||
[*]Chinese: [i]小紅帽[/i]
|
||||
[*]Italian: [i]Cappuccetto Rosso[/i]
|
||||
[*]Spanish: [i]Caperucita Roja[/i]
|
||||
[/list]
|
||||
[quote]It is about a girl called [color=#FF0000]Little Red Riding Hood :)[/color], after the red [url=http://en.wikipedia.org/wiki/Hood_%28headgear%29]hooded[/url] [url=http://en.wikipedia.org/wiki/Cape]cape[/url] or [url=http://en.wikipedia.org/wiki/Cloak]cloak[/url] she wears.
|
||||
The girl walks through the woods to deliver food to her sick grandmother. A wolf wants to eat the girl but is afraid to do so in public. He approaches the girl, and she naïvely tells him where she is going.
|
||||
He suggests the girl pick some flowers, which she does. In the meantime, he goes to the grandmother's house and gains entry by pretending to be the girl. He swallows the grandmother whole, and waits for the girl, disguised as the grandmother. When the girl arrives, she notices he looks very strange to be her grandma. In most retellings, this eventually culminates with Little Red Riding Hood saying, "My, what big teeth you have!"
|
||||
To which the wolf replies, "The better to eat you with," and swallows her whole, too.[/quote]
|
||||
The above version most widely known today is based on the [url=http://en.wikipedia.org/wiki/Brothers_Grimm]Brothers Grimm[/url] variant.
|
||||
</textarea>
|
||||
</div>
|
||||
<div id="preview">
|
||||
<h3 for="console">BBCode Output: </h3>
|
||||
<pre id="console">
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<hr>
|
||||
<p>
|
||||
CKEditor - The text editor for the Internet - <a class="samples" href="https://ckeditor.com/">https://ckeditor.com</a>
|
||||
</p>
|
||||
<p id="copy">
|
||||
Copyright © 2003-2019, <a class="samples" href="https://cksource.com/">CKSource</a> - Frederico
|
||||
Knabben. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var editor = CKEDITOR.replace( 'editor1', {
|
||||
extraPlugins: 'bbcode',
|
||||
// Remove unused plugins.
|
||||
removePlugins: 'bidi,dialogadvtab,div,filebrowser,flash,format,forms,horizontalrule,iframe,justify,liststyle,pagebreak,showborders,stylescombo,table,tabletools,templates',
|
||||
// Width and height are not supported in the BBCode format, so object resizing is disabled.
|
||||
disableObjectResizing: true,
|
||||
height: 250,
|
||||
toolbar: [
|
||||
['Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo'],
|
||||
['Find', 'Replace', '-', 'SelectAll', 'RemoveFormat'],
|
||||
['Link', 'Unlink', 'Image'],
|
||||
'/',
|
||||
['FontSize', 'Bold', 'Italic', 'Underline'],
|
||||
['NumberedList', 'BulletedList', '-', 'Blockquote'],
|
||||
['TextColor', '-', 'Smiley', 'SpecialChar', '-', 'Maximize']
|
||||
],
|
||||
// Define font sizes in percent values.
|
||||
fontSize_sizes: '30/30%;50/50%;100/100%;120/120%;150/150%;200/200%;300/300%',
|
||||
// Strip CKEditor smileys to those commonly used in BBCode.
|
||||
smiley_images: [
|
||||
'regular_smile.png', 'sad_smile.png', 'wink_smile.png', 'teeth_smile.png', 'tongue_smile.png',
|
||||
'embarrassed_smile.png', 'omg_smile.png', 'whatchutalkingabout_smile.png', 'angel_smile.png',
|
||||
'shades_smile.png', 'cry_smile.png', 'kiss.png'
|
||||
],
|
||||
smiley_descriptions: [
|
||||
'smiley', 'sad', 'wink', 'laugh', 'cheeky', 'blush', 'surprise',
|
||||
'indecision', 'angel', 'cool', 'crying', 'kiss'
|
||||
]
|
||||
} );
|
||||
|
||||
function updatePreview() {
|
||||
var consoleEl = CKEDITOR.document.getById( 'console' );
|
||||
consoleEl.addClass( 'updated' );
|
||||
setTimeout( function() { consoleEl.removeClass( 'updated' ); }, 500 );
|
||||
// IE needs <br>, it doesn't even understand new lines.
|
||||
consoleEl.setHtml( editor.getData().replace( /\n\r?/g, '<br>' ) );
|
||||
}
|
||||
|
||||
function checkUpdatePreview() {
|
||||
setTimeout( function() {
|
||||
if ( editor.checkDirty() ) {
|
||||
updatePreview();
|
||||
editor.resetDirty();
|
||||
}
|
||||
}, 0 );
|
||||
}
|
||||
|
||||
editor.on( 'instanceReady', updatePreview );
|
||||
editor.on( 'key', checkUpdatePreview );
|
||||
editor.on( 'selectionChange', checkUpdatePreview );
|
||||
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,8 @@
|
|||
/**
|
||||
* This software is licensed under MIT License
|
||||
* A markdown output plugin for CKEDITOR.
|
||||
* Uses showdown.js for conversion and DOMPurifier for HTML filtering.
|
||||
*
|
||||
* This software is licensed under MIT License.
|
||||
*
|
||||
* Copyright (c) 2019 Jan Böhmer
|
||||
*
|
||||
|
@ -24,14 +27,15 @@
|
|||
|
||||
(function() {
|
||||
|
||||
var unchangedData = null;
|
||||
|
||||
function overrideDataProcessor(editor)
|
||||
{
|
||||
//Both showdown and DOMPurify must be loaded
|
||||
if(typeof(showdown) == 'undefined') return;
|
||||
if (typeof(DOMPurify) == 'undefined') return;
|
||||
|
||||
//If the dataprocessor were already be overriden do nothing
|
||||
if(editor.dataProcessor.markdown) return;
|
||||
|
||||
var converter = new showdown.Converter();
|
||||
//Set some useful options on Showdown
|
||||
converter.setFlavor('github');
|
||||
|
@ -42,25 +46,26 @@
|
|||
|
||||
editor.dataProcessor = {
|
||||
toDataFormat: function(html, fixForBody) {
|
||||
html = html.replace(/(\r\n|\n|\r)/gm,"");
|
||||
//html = html.replace(/(\r\n|\n|\r)/gm,"");
|
||||
html = html.replace('<br>', '\n');
|
||||
//Support for strikethrough
|
||||
//Support for strikethrough in markdown
|
||||
html = html.replace('<s>', '<del>').replace('</s>', '</del>');
|
||||
return converter.makeMarkdown(html);
|
||||
},
|
||||
toHtml: function(data) {
|
||||
if(unchangedData) {
|
||||
data = unchangedData;
|
||||
unchangedData = null;
|
||||
}
|
||||
//Strip html tags from data.
|
||||
//This is useful, to convert unsupported HTML feauters to plain text and adds an basic XSS protection
|
||||
//The HTML is inside an iframe so an XSS attack can not do much harm.
|
||||
data = DOMPurify.sanitize(data);
|
||||
|
||||
return tmp = converter.makeHtml(data);
|
||||
toHtml: function(data){
|
||||
//Convert markdown to HTML and remove unsafe things from it.
|
||||
var unsafe = converter.makeHtml(data);
|
||||
return DOMPurify.sanitize(unsafe);
|
||||
},
|
||||
//Mark this dataprocessor
|
||||
markdown: true
|
||||
};
|
||||
|
||||
//Set the original data
|
||||
if(editor.markdown_unchangedData) {
|
||||
editor.setData(editor.markdown_unchangedData);
|
||||
editor.markdown_unchangedData = null;
|
||||
}
|
||||
}
|
||||
|
||||
CKEDITOR.plugins.add( 'markdown', {
|
||||
|
@ -129,20 +134,19 @@
|
|||
var config = editor.config;
|
||||
|
||||
var rootPath = this.path;
|
||||
//We override the dataprocessor later (after we loaded t
|
||||
unchangedData = editor.getData();
|
||||
//We override the dataprocessor later (after we loaded the needes scripts), sow we need the save untouched data now.
|
||||
editor.markdown_unchangedData = editor.getData();
|
||||
|
||||
if (typeof(showdown) == 'undefined') {
|
||||
CKEDITOR.scriptLoader.load(rootPath + 'js/showdown.min.js', function() {
|
||||
overrideDataProcessor(editor);
|
||||
editor.setData(unchangedData);
|
||||
});
|
||||
}, CKEDITOR, true);
|
||||
}
|
||||
|
||||
if (typeof(DOMPurify) == 'undefined') {
|
||||
CKEDITOR.scriptLoader.load(rootPath + 'js/purify.min.js', function() {
|
||||
overrideDataProcessor(editor);
|
||||
});
|
||||
overrideDataProcessor()
|
||||
}, CKEDITOR, true);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -151,5 +155,4 @@
|
|||
overrideDataProcessor(editor);
|
||||
}
|
||||
} );
|
||||
|
||||
} )();
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
||||
For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>BBCode Plugin — CKEditor Sample</title>
|
||||
<script src="../../../ckeditor.js"></script>
|
||||
<script src="../../../samples/old/sample.js"></script>
|
||||
<link rel="stylesheet" href="../../../samples/old/sample.css">
|
||||
<meta name="ckeditor-sample-required-plugins" content="sourcearea">
|
||||
<meta name="ckeditor-sample-name" content="Output for BBCode">
|
||||
<meta name="ckeditor-sample-group" content="Additional Plugins">
|
||||
<meta name="ckeditor-sample-description" content="Configuring CKEditor to produce BBCode tags instead of HTML.">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="samples">
|
||||
<a href="../../../samples/old/index.html">CKEditor Samples</a> » BBCode Plugin
|
||||
</h1>
|
||||
<div class="warning deprecated">
|
||||
This sample is not maintained anymore. Check out its <a href="https://ckeditor.com/docs/ckeditor4/latest/examples/bbcode.html">brand new version in CKEditor Examples</a>.
|
||||
</div>
|
||||
<div class="description">
|
||||
<p>
|
||||
This sample shows how to configure CKEditor to output <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a> format instead of HTML.
|
||||
Please note that the editor configuration was modified to reflect what is needed in a BBCode editing environment.
|
||||
Smiley images, for example, were stripped to the emoticons that are commonly used in some BBCode dialects.
|
||||
</p>
|
||||
<p>
|
||||
Please note that currently there is no standard for the BBCode markup language, so its implementation
|
||||
for different platforms (message boards, blogs etc.) can vary. This means that before using CKEditor to
|
||||
output BBCode you may need to adjust the implementation to your own environment.
|
||||
</p>
|
||||
<p>
|
||||
A snippet of the configuration code can be seen below; check the source of this page for
|
||||
a full definition:
|
||||
</p>
|
||||
<pre class="samples">
|
||||
CKEDITOR.replace( 'editor1', {
|
||||
<strong>extraPlugins: 'bbcode',</strong>
|
||||
toolbar: [
|
||||
[ 'Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo' ],
|
||||
[ 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat' ],
|
||||
[ 'Link', 'Unlink', 'Image' ],
|
||||
'/',
|
||||
[ 'FontSize', 'Bold', 'Italic', 'Underline' ],
|
||||
[ 'NumberedList', 'BulletedList', '-', 'Blockquote' ],
|
||||
[ 'TextColor', '-', 'Smiley', 'SpecialChar', '-', 'Maximize' ]
|
||||
],
|
||||
... <i>some other configurations omitted here</i>
|
||||
}); </pre>
|
||||
</div>
|
||||
<form action="../../../samples/sample_posteddata.php" method="post">
|
||||
<p>
|
||||
<label for="editor1">
|
||||
Editor 1:
|
||||
</label>
|
||||
<textarea cols="80" id="editor1" name="editor1" rows="10">This is some [b]sample text[/b]. You are using [url=https://ckeditor.com/]CKEditor[/url].</textarea>
|
||||
<script>
|
||||
|
||||
// Replace the <textarea id="editor"> with an CKEditor
|
||||
// instance, using the "bbcode" plugin, shaping some of the
|
||||
// editor configuration to fit BBCode environment.
|
||||
CKEDITOR.replace( 'editor1', {
|
||||
extraPlugins: 'bbcode',
|
||||
// Remove unused plugins.
|
||||
removePlugins: 'bidi,dialogadvtab,div,filebrowser,flash,format,forms,horizontalrule,iframe,justify,liststyle,pagebreak,showborders,stylescombo,table,tabletools,templates',
|
||||
// Width and height are not supported in the BBCode format, so object resizing is disabled.
|
||||
disableObjectResizing: true,
|
||||
// Define font sizes in percent values.
|
||||
fontSize_sizes: "30/30%;50/50%;100/100%;120/120%;150/150%;200/200%;300/300%",
|
||||
toolbar: [
|
||||
[ 'Source', '-', 'Save', 'NewPage', '-', 'Undo', 'Redo' ],
|
||||
[ 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat' ],
|
||||
[ 'Link', 'Unlink', 'Image', 'Smiley', 'SpecialChar' ],
|
||||
'/',
|
||||
[ 'Bold', 'Italic', 'Underline' ],
|
||||
[ 'FontSize' ],
|
||||
[ 'TextColor' ],
|
||||
[ 'NumberedList', 'BulletedList', '-', 'Blockquote' ],
|
||||
[ 'Maximize' ]
|
||||
],
|
||||
// Strip CKEditor smileys to those commonly used in BBCode.
|
||||
smiley_images: [
|
||||
'regular_smile.png', 'sad_smile.png', 'wink_smile.png', 'teeth_smile.png', 'tongue_smile.png',
|
||||
'embarrassed_smile.png', 'omg_smile.png', 'whatchutalkingabout_smile.png', 'angel_smile.png',
|
||||
'shades_smile.png', 'cry_smile.png', 'kiss.png'
|
||||
],
|
||||
smiley_descriptions: [
|
||||
'smiley', 'sad', 'wink', 'laugh', 'cheeky', 'blush', 'surprise',
|
||||
'indecision', 'angel', 'cool', 'crying', 'kiss'
|
||||
]
|
||||
});
|
||||
|
||||
</script>
|
||||
</p>
|
||||
<p>
|
||||
<input type="submit" value="Submit">
|
||||
</p>
|
||||
</form>
|
||||
<div id="footer">
|
||||
<hr>
|
||||
<p>
|
||||
CKEditor - The text editor for the Internet - <a class="samples" href="https://ckeditor.com/">https://ckeditor.com</a>
|
||||
</p>
|
||||
<p id="copy">
|
||||
Copyright © 2003-2019, <a class="samples" href="https://cksource.com/">CKSource</a> - Frederico
|
||||
Knabben. All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue