Source/WebCore/ChangeLog

 12012-02-29 Pablo Flouret <pablof@motorola.com>
 2
 3 Implement DefaultParagraphSeparator execCommand, to let authors choose the default block element
 4 https://bugs.webkit.org/show_bug.cgi?id=59961
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 http://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-defaultparagraphseparator-command
 9
 10 Test: editing/execCommand/default-paragraph-separator.html
 11
 12 * editing/CompositeEditCommand.cpp:
 13 (WebCore::CompositeEditCommand::insertNewDefaultParagraphElementAt):
 14 (WebCore::CompositeEditCommand::breakOutOfEmptyListItem):
 15 * editing/Editor.cpp:
 16 (WebCore::Editor::Editor):
 17 (WebCore::Editor::createDefaultParagraphSeparatorElement):
 18 * editing/Editor.h:
 19 (WebCore::Editor::defaultParagraphSeparatorIsDiv):
 20 (WebCore::Editor::setDefaultParagraphSeparatorIsDiv):
 21 (Editor):
 22 * editing/EditorCommand.cpp:
 23 (WebCore::executeDefaultParagraphSeparator):
 24 (WebCore):
 25 (WebCore::valueDefaultParagraphSeparator):
 26 (WebCore::createCommandMap):
 27 * editing/InsertParagraphSeparatorCommand.cpp:
 28 (WebCore::InsertParagraphSeparatorCommand::doApply):
 29 * editing/ReplaceSelectionCommand.cpp:
 30 (WebCore::ReplacementFragment::insertFragmentForTestRendering):
 31 * editing/htmlediting.cpp:
 32 * editing/htmlediting.h:
 33 (WebCore):
 34 * editing/markup.cpp:
 35 (WebCore::createFragmentFromText):
 36 (WebCore::createFragmentFromNodes):
 37
 38 * html/HTMLParagraphElement.cpp:
 39 (WebCore::HTMLParagraphElement::create):
 40 (WebCore):
 41 * html/HTMLParagraphElement.h:
 42 (HTMLParagraphElement):
 43 Added create(Document*) method that defaults to pTag as the QualifiedName.
 44
 45 * page/Frame.cpp:
 46 (WebCore::Frame::setDocument):
 47
1482012-02-27 Chris Rogers <crogers@google.com>
249
350 Implement static compression curve parameters for DynamicsCompressorNode

Source/WebCore/editing/CompositeEditCommand.cpp

@@void CompositeEditCommand::removePlaceholderAt(const Position& p)
866866
867867PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
868868{
869  RefPtr<Element> paragraphElement = createDefaultParagraphElement(document());
 869 RefPtr<Element> paragraphElement = document()->frame()->editor()->createDefaultParagraphSeparatorElement(document());
870870 ExceptionCode ec;
871871 paragraphElement->appendChild(createBreakElement(document()), ec);
872872 insertNodeAt(paragraphElement, position);

@@bool CompositeEditCommand::breakOutOfEmptyListItem()
12581258 newBlock = createListItemElement(document());
12591259 }
12601260 if (!newBlock)
1261  newBlock = createDefaultParagraphElement(document());
 1261 newBlock = document()->frame()->editor()->createDefaultParagraphSeparatorElement(document());
12621262
12631263 if (emptyListItem->renderer()->nextSibling()) {
12641264 // If emptyListItem follows another list item, split the list node.

Source/WebCore/editing/Editor.cpp

5252#include "FrameTree.h"
5353#include "FrameView.h"
5454#include "GraphicsContext.h"
 55#include "HTMLDivElement.h"
5556#include "HTMLFormControlElement.h"
5657#include "HTMLFrameOwnerElement.h"
5758#include "HTMLNames.h"
 59#include "HTMLParagraphElement.h"
5860#include "HTMLTextAreaElement.h"
5961#include "HitTestResult.h"
6062#include "IndentOutdentCommand.h"

@@Editor::Editor(Frame* frame)
846848 , m_spellChecker(adoptPtr(new SpellChecker(frame)))
847849 , m_spellingCorrector(adoptPtr(new SpellingCorrectionController(frame)))
848850 , m_areMarkedTextMatchesHighlighted(false)
 851 , m_defaultParagraphSeparatorIsDiv(true)
849852{
850853}
851854

@@bool Editor::unifiedTextCheckerEnabled() const
30183021 return WebCore::unifiedTextCheckerEnabled(m_frame);
30193022}
30203023
 3024PassRefPtr<HTMLElement> Editor::createDefaultParagraphSeparatorElement(Document* document) const
 3025{
 3026 if (defaultParagraphSeparatorIsDiv())
 3027 return HTMLDivElement::create(document);
 3028 return HTMLParagraphElement::create(document);
 3029}
30213030} // namespace WebCore

Source/WebCore/editing/Editor.h

@@public:
383383
384384 void deviceScaleFactorChanged();
385385
 386 bool defaultParagraphSeparatorIsDiv() const { return m_defaultParagraphSeparatorIsDiv; }
 387 void setDefaultParagraphSeparatorIsDiv(bool isDiv) { m_defaultParagraphSeparatorIsDiv = isDiv; };
 388 PassRefPtr<HTMLElement> createDefaultParagraphSeparatorElement(Document*) const;
 389
386390private:
387391 Frame* m_frame;
388392 OwnPtr<DeleteButtonController> m_deleteButtonController;

@@private:
400404 OwnPtr<SpellingCorrectionController> m_spellingCorrector;
401405 VisibleSelection m_mark;
402406 bool m_areMarkedTextMatchesHighlighted;
 407 bool m_defaultParagraphSeparatorIsDiv; // Should be P otherwise.
403408
404409 bool canDeleteRange(Range*) const;
405410 bool canSmartReplaceWithPasteboard(Pasteboard*);

Source/WebCore/editing/EditorCommand.cpp

@@static bool executeCut(Frame* frame, Event*, EditorCommandSource source, const S
307307 return true;
308308}
309309
 310static bool executeDefaultParagraphSeparator(Frame* frame, Event*, EditorCommandSource, const String& value)
 311{
 312 if (equalIgnoringCase(value, "div"))
 313 frame->editor()->setDefaultParagraphSeparatorIsDiv(true);
 314 else if (equalIgnoringCase(value, "p"))
 315 frame->editor()->setDefaultParagraphSeparatorIsDiv(false);
 316
 317 return true;
 318}
 319
310320static bool executeDelete(Frame* frame, Event*, EditorCommandSource source, const String&)
311321{
312322 switch (source) {

@@static String valueBackColor(Frame* frame, Event*)
13781388 return valueStyle(frame, CSSPropertyBackgroundColor);
13791389}
13801390
 1391static String valueDefaultParagraphSeparator(Frame* frame, Event*)
 1392{
 1393 return frame->editor()->defaultParagraphSeparatorIsDiv() ? "div" : "p";
 1394}
 1395
13811396static String valueFontName(Frame* frame, Event*)
13821397{
13831398 return valueStyle(frame, CSSPropertyFontFamily);

@@static const CommandMap& createCommandMap()
14291444 { "Copy", { executeCopy, supportedCopyCut, enabledCopy, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
14301445 { "CreateLink", { executeCreateLink, supported, enabledInRichlyEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
14311446 { "Cut", { executeCut, supportedCopyCut, enabledCut, stateNone, valueNull, notTextInsertion, allowExecutionWhenDisabled } },
 1447 { "DefaultParagraphSeparator", { executeDefaultParagraphSeparator, supported, enabled, stateNone, valueDefaultParagraphSeparator, notTextInsertion, doNotAllowExecutionWhenDisabled} },
14321448 { "Delete", { executeDelete, supported, enabledDelete, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
14331449 { "DeleteBackward", { executeDeleteBackward, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },
14341450 { "DeleteBackwardByDecomposingPreviousCharacter", { executeDeleteBackwardByDecomposingPreviousCharacter, supportedFromMenuOrKeyBinding, enabledInEditableText, stateNone, valueNull, notTextInsertion, doNotAllowExecutionWhenDisabled } },

Source/WebCore/editing/InsertParagraphSeparatorCommand.cpp

2929#include "CSSPropertyNames.h"
3030#include "Document.h"
3131#include "EditingStyle.h"
 32#include "Editor.h"
 33#include "Frame.h"
3234#include "HTMLElement.h"
3335#include "HTMLNames.h"
3436#include "InsertLineBreakCommand.h"

@@void InsertParagraphSeparatorCommand::doApply()
203205 // Create block to be inserted.
204206 RefPtr<Element> blockToInsert;
205207 if (startBlock == startBlock->rootEditableElement()) {
206  blockToInsert = createDefaultParagraphElement(document());
 208 blockToInsert = document()->frame()->editor()->createDefaultParagraphSeparatorElement(document());
207209 nestNewBlock = true;
208210 } else if (shouldUseDefaultParagraphElement(startBlock))
209  blockToInsert = createDefaultParagraphElement(document());
 211 blockToInsert = document()->frame()->editor()->createDefaultParagraphSeparatorElement(document());
210212 else
211213 blockToInsert = startBlock->cloneElementWithoutChildren();
212214

@@void InsertParagraphSeparatorCommand::doApply()
218220 if (isFirstInBlock && !lineBreakExistsAtVisiblePosition(visiblePos)) {
219221 // The block is empty. Create an empty block to
220222 // represent the paragraph that we're leaving.
221  RefPtr<Element> extraBlock = createDefaultParagraphElement(document());
 223 RefPtr<Element> extraBlock = document()->frame()->editor()->createDefaultParagraphSeparatorElement(document());
222224 appendNode(extraBlock, startBlock);
223225 appendBlockPlaceholder(extraBlock);
224226 }

Source/WebCore/editing/ReplaceSelectionCommand.cpp

@@void ReplacementFragment::insertNodeBefore(PassRefPtr<Node> node, Node* refNode)
247247
248248PassRefPtr<StyledElement> ReplacementFragment::insertFragmentForTestRendering(Node* rootEditableElement)
249249{
250  RefPtr<StyledElement> holder = createDefaultParagraphElement(m_document.get());
 250 RefPtr<StyledElement> holder = m_document->frame()->editor()->createDefaultParagraphSeparatorElement(m_document.get());
251251
252252 ExceptionCode ec = 0;
253253

Source/WebCore/editing/htmlediting.cpp

@@bool isEmptyTableCell(const Node* node)
842842 return !childRenderer->nextSibling();
843843}
844844
845 PassRefPtr<HTMLElement> createDefaultParagraphElement(Document* document)
846 {
847  return HTMLDivElement::create(document);
848 }
849 
850845PassRefPtr<HTMLElement> createBreakElement(Document* document)
851846{
852847 return HTMLBRElement::create(document);

Source/WebCore/editing/htmlediting.h

@@PassRefPtr<Range> avoidIntersectionWithNode(const Range*, Node*);
199199
200200// Functions returning HTMLElement
201201
202 PassRefPtr<HTMLElement> createDefaultParagraphElement(Document*);
203202PassRefPtr<HTMLElement> createBreakElement(Document*);
204203PassRefPtr<HTMLElement> createOrderedListElement(Document*);
205204PassRefPtr<HTMLElement> createUnorderedListElement(Document*);

Source/WebCore/editing/markup.cpp

@@PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
900900 if (useClonesOfEnclosingBlock)
901901 element = block->cloneElementWithoutChildren();
902902 else
903  element = createDefaultParagraphElement(document);
 903 element = document->frame()->editor()->createDefaultParagraphSeparatorElement(document);
904904 fillContainerFromString(element.get(), s);
905905 }
906906 fragment->appendChild(element.release(), ec);

@@PassRefPtr<DocumentFragment> createFragmentFromNodes(Document *document, const V
923923 ExceptionCode ec = 0;
924924 size_t size = nodes.size();
925925 for (size_t i = 0; i < size; ++i) {
926  RefPtr<Element> element = createDefaultParagraphElement(document);
 926 RefPtr<Element> element = document->frame()->editor()->createDefaultParagraphSeparatorElement(document);
927927 element->appendChild(nodes[i], ec);
928928 ASSERT(!ec);
929929 fragment->appendChild(element.release(), ec);

Source/WebCore/html/HTMLParagraphElement.cpp

@@inline HTMLParagraphElement::HTMLParagraphElement(const QualifiedName& tagName,
3939 ASSERT(hasTagName(pTag));
4040}
4141
 42PassRefPtr<HTMLParagraphElement> HTMLParagraphElement::create(Document* document)
 43{
 44 return adoptRef(new HTMLParagraphElement(pTag, document));
 45}
 46
4247PassRefPtr<HTMLParagraphElement> HTMLParagraphElement::create(const QualifiedName& tagName, Document* document)
4348{
4449 return adoptRef(new HTMLParagraphElement(tagName, document));

Source/WebCore/html/HTMLParagraphElement.h

@@namespace WebCore {
2929
3030class HTMLParagraphElement : public HTMLElement {
3131public:
 32 static PassRefPtr<HTMLParagraphElement> create(Document*);
3233 static PassRefPtr<HTMLParagraphElement> create(const QualifiedName&, Document*);
3334
3435private:

Source/WebCore/page/Frame.cpp

@@void Frame::setDocument(PassRefPtr<Document> newDoc)
306306 notifyChromeClientWheelEventHandlerCountChanged();
307307 notifyChromeClientTouchEventHandlerCountChanged();
308308 }
 309
 310 // Reset the editor's default paragraph separator to the default value (a div).
 311 m_editor.setDefaultParagraphSeparatorIsDiv(true);
309312}
310313
311314#if ENABLE(ORIENTATION_EVENTS)

LayoutTests/ChangeLog

 12012-02-29 Pablo Flouret <pablof@motorola.com>
 2
 3 Implement DefaultParagraphSeparator execCommand, to let authors choose the default block element
 4 https://bugs.webkit.org/show_bug.cgi?id=59961
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * editing/execCommand/default-paragraph-separator-expected.txt: Added.
 9 * editing/execCommand/default-paragraph-separator.html: Added.
 10
1112012-02-27 Chris Rogers <crogers@google.com>
212
313 Implement static compression curve parameters for DynamicsCompressorNode

LayoutTests/editing/execCommand/default-paragraph-separator-expected.txt

 1PASS document.queryCommandEnabled('DefaultParagraphSeparator') is true
 2PASS document.queryCommandValue('DefaultParagraphSeparator') is "div"
 3document.execCommand('DefaultParagraphSeparator', false, 'p')
 4PASS document.queryCommandValue('DefaultParagraphSeparator') is "p"
 5document.execCommand('DefaultParagraphSeparator', false, 'br')
 6PASS document.queryCommandValue('DefaultParagraphSeparator') is "p"
 7document.execCommand('DefaultParagraphSeparator', false, 'invalid')
 8PASS document.queryCommandValue('DefaultParagraphSeparator') is "p"
 9
 10Creating paragraphs in the normal way.
 11document.execCommand('InsertText', false, 'a')
 12PASS div.innerHTML is "a"
 13document.execCommand('InsertText', false, '\n')
 14PASS div.innerHTML is "a<p><br></p>"
 15document.execCommand('InsertText', false, 'b')
 16PASS div.innerHTML is "a<p>b</p>"
 17document.execCommand('InsertText', false, '\n')
 18PASS div.innerHTML is "a<p>b</p><p><br></p>"
 19document.execCommand('Delete')
 20PASS div.innerHTML is "a<p>b</p>"
 21document.execCommand('Delete')
 22PASS div.innerHTML is "a<p><br></p>"
 23document.execCommand('Delete')
 24PASS div.innerHTML is "a"
 25document.execCommand('DefaultParagraphSeparator', false, 'div')
 26document.execCommand('InsertParagraph')
 27PASS div.innerHTML is "a<div><br></div>"
 28div.innerHTML = ''
 29
 30Using the previous block as template for the new one.
 31document.execCommand('DefaultParagraphSeparator', false, 'p')
 32document.execCommand("InsertHTML", false, "<pre>a</pre>");
 33PASS div.innerHTML is "<pre>a</pre>"
 34document.execCommand('InsertText', false, 'b')
 35PASS div.innerHTML is "<pre>ab</pre>"
 36document.execCommand('InsertText', false, '\n')
 37PASS div.innerHTML is "<pre>ab</pre><pre><br></pre>"
 38document.execCommand('InsertText', false, 'c')
 39PASS div.innerHTML is "<pre>ab</pre><pre>c</pre>"
 40document.execCommand('DefaultParagraphSeparator', false, 'div')
 41document.execCommand('InsertText', false, '\n')
 42PASS div.innerHTML is "<pre>ab</pre><pre>c</pre><pre><br></pre>"
 43document.execCommand('Delete')
 44document.execCommand('InsertParagraph')
 45PASS div.innerHTML is "<pre>ab</pre><pre>c</pre><pre><br></pre>"
 46
 47Breaking out of lists.
 48div.innerHTML = ''
 49document.execCommand('DefaultParagraphSeparator', false, 'p')
 50document.execCommand("InsertHTML", false, "<ul><li>a</li></ul>")
 51PASS div.innerHTML is "<ul><li>a</li></ul>"
 52document.execCommand('InsertParagraph')
 53document.execCommand('InsertParagraph')
 54PASS div.innerHTML is "<ul><li>a</li></ul><p><br></p>"
 55
 56Breaking up nested elements.
 57div.innerHTML = ''
 58document.execCommand("InsertHTML", false, "<cite>a<cite>bc</cite></cite>")
 59selection.modify("move", "backward", "character")
 60document.execCommand('InsertParagraph')
 61PASS div.innerHTML is "<cite>a<cite>b</cite></cite><p><cite><cite>c</cite></cite></p>"
 62PASS successfullyParsed is true
 63
 64TEST COMPLETE
 65

LayoutTests/editing/execCommand/default-paragraph-separator.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../fast/js/resources/js-test-pre.js"></script>
 5<script src="../editing.js"></script>
 6</head>
 7<body>
 8<div id=editor contenteditable></div>
 9<script>
 10 shouldBeTrue("document.queryCommandEnabled('DefaultParagraphSeparator')");
 11 shouldBeEqualToString("document.queryCommandValue('DefaultParagraphSeparator')", "div"); // Default is div.
 12 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'p')");
 13 shouldBeEqualToString("document.queryCommandValue('DefaultParagraphSeparator')", "p");
 14 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'br')");
 15 shouldBeEqualToString("document.queryCommandValue('DefaultParagraphSeparator')", "p");
 16 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'invalid')");
 17 shouldBeEqualToString("document.queryCommandValue('DefaultParagraphSeparator')", "p");
 18
 19 debug("\nCreating paragraphs in the normal way.");
 20 var div = document.querySelector("#editor");
 21 div.focus();
 22 evalAndLog("document.execCommand('InsertText', false, 'a')");
 23 shouldBeEqualToString("div.innerHTML", "a");
 24 evalAndLog("document.execCommand('InsertText', false, '\\n')");
 25 shouldBeEqualToString("div.innerHTML", "a<p><br></p>");
 26 evalAndLog("document.execCommand('InsertText', false, 'b')");
 27 shouldBeEqualToString("div.innerHTML", "a<p>b</p>");
 28 evalAndLog("document.execCommand('InsertText', false, '\\n')");
 29 shouldBeEqualToString("div.innerHTML", "a<p>b</p><p><br></p>");
 30 evalAndLog("document.execCommand('Delete')");
 31 shouldBeEqualToString("div.innerHTML", "a<p>b</p>");
 32 evalAndLog("document.execCommand('Delete')");
 33 shouldBeEqualToString("div.innerHTML", "a<p><br></p>");
 34 evalAndLog("document.execCommand('Delete')");
 35 shouldBeEqualToString("div.innerHTML", "a");
 36 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'div')");
 37 evalAndLog("document.execCommand('InsertParagraph')");
 38 shouldBeEqualToString("div.innerHTML", "a<div><br></div>");
 39 evalAndLog("div.innerHTML = ''");
 40
 41 debug("\nUsing the previous block as template for the new one.");
 42 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'p')");
 43 debug('document.execCommand("InsertHTML", false, "&lt;pre&gt;a&lt;/pre&gt;");');
 44 document.execCommand("InsertHTML", false, "<pre>a</pre>");
 45 shouldBeEqualToString("div.innerHTML", "<pre>a</pre>");
 46 evalAndLog("document.execCommand('InsertText', false, 'b')");
 47 shouldBeEqualToString("div.innerHTML", "<pre>ab</pre>");
 48 evalAndLog("document.execCommand('InsertText', false, '\\n')");
 49 shouldBeEqualToString("div.innerHTML", "<pre>ab</pre><pre><br></pre>");
 50 evalAndLog("document.execCommand('InsertText', false, 'c')");
 51 shouldBeEqualToString("div.innerHTML", "<pre>ab</pre><pre>c</pre>");
 52 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'div')");
 53 evalAndLog("document.execCommand('InsertText', false, '\\n')");
 54 shouldBeEqualToString("div.innerHTML", "<pre>ab</pre><pre>c</pre><pre><br></pre>");
 55 evalAndLog("document.execCommand('Delete')");
 56 evalAndLog("document.execCommand('InsertParagraph')");
 57 shouldBeEqualToString("div.innerHTML", "<pre>ab</pre><pre>c</pre><pre><br></pre>");
 58
 59 debug("\nBreaking out of lists.");
 60 evalAndLog("div.innerHTML = ''");
 61 evalAndLog("document.execCommand('DefaultParagraphSeparator', false, 'p')");
 62 debug('document.execCommand("InsertHTML", false, "&lt;ul>&lt;li>a&lt;/li>&lt;/ul>")');
 63 document.execCommand("InsertHTML", false, "<ul><li>a</li></ul>");
 64 shouldBeEqualToString("div.innerHTML", "<ul><li>a</li></ul>");
 65 evalAndLog("document.execCommand('InsertParagraph')");
 66 evalAndLog("document.execCommand('InsertParagraph')");
 67 shouldBeEqualToString("div.innerHTML", "<ul><li>a</li></ul><p><br></p>");
 68
 69 debug("\nBreaking up nested elements.");
 70 evalAndLog("div.innerHTML = ''");
 71 debug('document.execCommand("InsertHTML", false, "&lt;cite>a&lt;cite>bc&lt;/cite>&lt;/cite>")');
 72 document.execCommand("InsertHTML", false, "<cite>a<cite>bc</cite></cite>");
 73 evalAndLog('selection.modify("move", "backward", "character")');
 74 evalAndLog("document.execCommand('InsertParagraph')");
 75 shouldBeEqualToString("div.innerHTML", "<cite>a<cite>b</cite></cite><p><cite><cite>c</cite></cite></p>");
 76
 77 div.innerHTML = "";
 78</script>
 79<script src="../../fast/js/resources/js-test-post.js"></script>
 80</body>
 81</html>