X-Git-Url: https://scm.cri.ensmp.fr/git/ckeditor.git/blobdiff_plain/871bad8291b6dbc29d489d95d185458caab25158..14d450d78a2d67ec1decd64c928151851961dd36:/_source/core/htmlparser/fragment.js diff --git a/_source/core/htmlparser/fragment.js b/_source/core/htmlparser/fragment.js deleted file mode 100644 index bfa5cc5..0000000 --- a/_source/core/htmlparser/fragment.js +++ /dev/null @@ -1,497 +0,0 @@ -/* -Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved. -For licensing, see LICENSE.html or http://ckeditor.com/license -*/ - -/** - * A lightweight representation of an HTML DOM structure. - * @constructor - * @example - */ -CKEDITOR.htmlParser.fragment = function() -{ - /** - * The nodes contained in the root of this fragment. - * @type Array - * @example - * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( 'Sample Text' ); - * alert( fragment.children.length ); "2" - */ - this.children = []; - - /** - * Get the fragment parent. Should always be null. - * @type Object - * @default null - * @example - */ - this.parent = null; - - /** @private */ - this._ = - { - isBlockLike : true, - hasInlineStarted : false - }; -}; - -(function() -{ - // Block-level elements whose internal structure should be respected during - // parser fixing. - var nonBreakingBlocks = CKEDITOR.tools.extend( { table:1,ul:1,ol:1,dl:1 }, CKEDITOR.dtd.table, CKEDITOR.dtd.ul, CKEDITOR.dtd.ol, CKEDITOR.dtd.dl ); - - // IE < 8 don't output the close tag on definition list items. (#6975) - var optionalCloseTags = CKEDITOR.env.ie && CKEDITOR.env.version < 8 ? { dd : 1, dt :1 } : {}; - - var listBlocks = { ol:1, ul:1 }; - - // Dtd of the fragment element, basically it accept anything except for intermediate structure, e.g. orphan
element, spaces should be touched differently. - inPre = false; - - function checkPending( newTagName ) - { - var pendingBRsSent; - - 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 ] ) ) - { - if ( !pendingBRsSent ) - { - sendPendingBRs(); - pendingBRsSent = 1; - } - - // 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 sendPendingBRs() - { - while ( pendingBRs.length ) - currentNode.add( pendingBRs.shift() ); - } - - /* - * Beside of simply append specified element to target, this function also takes - * care of other dirty lifts like forcing block in body, trimming spaces at - * the block boundaries etc. - * - * @param {Element} element The element to be added as the last child of {@link target}. - * @param {Element} target The parent element to relieve the new node. - * @param {Boolean} [moveCurrent=false] Don't change the "currentNode" global unless - * there's a return point node specified on the element, otherwise move current onto {@link target} node. - */ - function addElement( element, target, moveCurrent ) - { - // Ignore any element that has already been added. - if ( element.previous !== undefined ) - return; - - target = target || currentNode || fragment; - - // Current element might be mangled by fix body below, - // save it for restore later. - var savedCurrent = currentNode; - - // If the target is the fragment and this inline element can't go inside - // body (if fixForBody). - if ( fixForBody && ( !target.type || target.name == 'body' ) ) - { - var elementName, realElementName; - if ( element.attributes - && ( realElementName = - element.attributes[ 'data-cke-real-element-type' ] ) ) - elementName = realElementName; - else - elementName = element.name; - - if ( elementName && !( elementName in CKEDITOR.dtd.$body || elementName == 'body' || element.isOrphan ) ) - { - // Create ain the fragment. - currentNode = target; - parser.onTagOpen( fixForBody, {} ); - - // The new target now is the
. - element.returnPoint = target = currentNode; - } - } - - // Rtrim empty spaces on block end boundary. (#3585) - if ( element._.isBlockLike - && element.name != 'pre' ) - { - - var length = element.children.length, - lastChild = element.children[ length - 1 ], - text; - if ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT ) - { - if ( !( text = CKEDITOR.tools.rtrim( lastChild.value ) ) ) - element.children.length = length -1; - else - lastChild.value = text; - } - } - - target.add( element ); - - if ( element.returnPoint ) - { - currentNode = element.returnPoint; - delete element.returnPoint; - } - else - currentNode = moveCurrent ? target : savedCurrent; - } - - parser.onTagOpen = function( tagName, attributes, selfClosing, optionalClose ) - { - var element = new CKEDITOR.htmlParser.element( tagName, attributes ); - - // "isEmpty" will be always "false" for unknown elements, so we - // must force it if the parser has identified it as a selfClosing tag. - if ( element.isUnknown && selfClosing ) - element.isEmpty = true; - - // Check for optional closed elements, including browser quirks and manually opened blocks. - element.isOptionalClose = tagName in optionalCloseTags || optionalClose; - - // This is a tag to be removed if empty, so do not add it immediately. - if ( CKEDITOR.dtd.$removeEmpty[ tagName ] ) - { - pendingInline.push( element ); - return; - } - else if ( tagName == 'pre' ) - inPre = true; - else if ( tagName == 'br' && inPre ) - { - currentNode.add( new CKEDITOR.htmlParser.text( '\n' ) ); - return; - } - - if ( tagName == 'br' ) - { - pendingBRs.push( element ); - return; - } - - while( 1 ) - { - var currentName = currentNode.name; - - var currentDtd = currentName ? ( CKEDITOR.dtd[ currentName ] - || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) ) - : rootDtd; - - // If the element cannot be child of the current element. - if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] ) - { - // Current node doesn't have a close tag, time for a close - // as this element isn't fit in. (#7497) - if ( currentNode.isOptionalClose ) - parser.onTagClose( currentName ); - // Fixing malformed nested lists by moving it into a previous list item. (#3828) - else if ( tagName in listBlocks - && currentName in listBlocks ) - { - var children = currentNode.children, - lastChild = children[ children.length - 1 ]; - - // Establish the list item if it's not existed. - if ( !( lastChild && lastChild.name == 'li' ) ) - addElement( ( lastChild = new CKEDITOR.htmlParser.element( 'li' ) ), currentNode ); - - !element.returnPoint && ( element.returnPoint = currentNode ); - currentNode = lastChild; - } - // Establish new list root for orphan list items. - else if ( tagName in CKEDITOR.dtd.$listItem && currentName != tagName ) - parser.onTagOpen( tagName == 'li' ? 'ul' : 'dl', {}, 0, 1 ); - // We're inside a structural block like table and list, AND the incoming element - // is not of the same type (e.g.
td1 td2 ), we simply add this new one before it, - // and most importantly, return back to here once this element is added, - // e.g.
td1 | td2 |
. - if ( ( !currentNode._.hasInlineStarted || pendingBRs.length ) && !inPre ) - { - text = CKEDITOR.tools.ltrim( text ); - - if ( text.length === 0 ) - return; - } - - sendPendingBRs(); - checkPending(); - - if ( fixForBody - && ( !currentNode.type || currentNode.name == 'body' ) - && CKEDITOR.tools.trim( text ) ) - { - this.onTagOpen( fixForBody, {}, 0, 1 ); - } - - // Shrinking consequential spaces into one single for all elements - // text contents. - if ( !inPre ) - text = text.replace( /[\t\r\n ]{2,}|[\t\r\n]/g, ' ' ); - - currentNode.add( new CKEDITOR.htmlParser.text( text ) ); - }; - - parser.onCDATA = function( cdata ) - { - currentNode.add( new CKEDITOR.htmlParser.cdata( cdata ) ); - }; - - parser.onComment = function( comment ) - { - sendPendingBRs(); - checkPending(); - currentNode.add( new CKEDITOR.htmlParser.comment( comment ) ); - }; - - // Parse it. - parser.parse( fragmentHtml ); - - // Send all pending BRs except one, which we consider a unwanted bogus. (#5293) - sendPendingBRs( !CKEDITOR.env.ie && 1 ); - - // Close all pending nodes, make sure return point is properly restored. - while ( currentNode != fragment ) - addElement( currentNode, currentNode.parent, 1 ); - - return fragment; - }; - - CKEDITOR.htmlParser.fragment.prototype = - { - /** - * Adds a node to this fragment. - * @param {Object} node The node to be added. It can be any of of the - * following types: {@link CKEDITOR.htmlParser.element}, - * {@link CKEDITOR.htmlParser.text} and - * {@link CKEDITOR.htmlParser.comment}. - * @param {Number} [index] From where the insertion happens. - * @example - */ - add : function( node, index ) - { - isNaN( index ) && ( index = this.children.length ); - - var previous = index > 0 ? this.children[ index - 1 ] : null; - if ( previous ) - { - // If the block to be appended is following text, trim spaces at - // the right of it. - if ( node._.isBlockLike && previous.type == CKEDITOR.NODE_TEXT ) - { - previous.value = CKEDITOR.tools.rtrim( previous.value ); - - // If we have completely cleared the previous node. - if ( previous.value.length === 0 ) - { - // Remove it from the list and add the node again. - this.children.pop(); - this.add( node ); - return; - } - } - - previous.next = node; - } - - node.previous = previous; - node.parent = this; - - this.children.splice( index, 0, node ); - - this._.hasInlineStarted = node.type == CKEDITOR.NODE_TEXT || ( node.type == CKEDITOR.NODE_ELEMENT && !node._.isBlockLike ); - }, - - /** - * Writes the fragment HTML to a CKEDITOR.htmlWriter. - * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML. - * @example - * var writer = new CKEDITOR.htmlWriter(); - * var fragment = CKEDITOR.htmlParser.fragment.fromHtml( '<P><B>Example' ); - * fragment.writeHtml( writer ) - * alert( writer.getHtml() ); "<p><b>Example</b></p>" - */ - writeHtml : function( writer, filter ) - { - var isChildrenFiltered; - this.filterChildren = function() - { - var writer = new CKEDITOR.htmlParser.basicWriter(); - this.writeChildrenHtml.call( this, writer, filter, true ); - var html = writer.getHtml(); - this.children = new CKEDITOR.htmlParser.fragment.fromHtml( html ).children; - isChildrenFiltered = 1; - }; - - // Filtering the root fragment before anything else. - !this.name && filter && filter.onFragment( this ); - - this.writeChildrenHtml( writer, isChildrenFiltered ? null : filter ); - }, - - writeChildrenHtml : function( writer, filter ) - { - for ( var i = 0 ; i < this.children.length ; i++ ) - this.children[i].writeHtml( writer, filter ); - } - }; -})();