editor: first take on plugins, core plugin with breakContent transformation
authorAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Sun, 8 Dec 2013 15:17:02 +0000 (16:17 +0100)
committerAleksander Łukasz <aleksander.lukasz@nowoczesnapolska.org.pl>
Sun, 15 Dec 2013 21:32:49 +0000 (22:32 +0100)
src/editor/entrypoint.js
src/editor/modules/data/data.js
src/editor/modules/documentCanvas/canvas/keyboard.js
src/editor/plugins/core/core.js [new file with mode: 0644]
src/editor/plugins/core/core.test.js [new file with mode: 0644]
src/fnpjs/runner.js

index 20460b3..ac19d6e 100644 (file)
         '../fnpjs/runner',
         'rng',
         './modules',
+        'plugins/core/core',
         'libs/bootstrap'
-    ], function($, runner, rng, modules) {
+    ], function($, runner, rng, modules, corePlugin) {
         $(function() {
             var app = new runner.Runner(rng, modules);
             app.setBootstrappedData('data', RNG_BOOTSTRAP_DATA);
+            app.registerPlugin(corePlugin);
             app.start({rootSelector:'#editor_root'});
         });
     });
index e90a1b6..006bf0f 100644 (file)
@@ -18,6 +18,11 @@ return function(sandbox) {
     var wlxmlDocument = wlxml.WLXMLDocumentFromXML(sandbox.getBootstrappedData().document);
 
     wlxmlDocument.registerExtension(listExtension);
+    sandbox.getPlugins().forEach(function(plugin) {
+        if(plugin.documentExtension) {
+            wlxmlDocument.registerExtension(plugin.documentExtension);
+        }
+    });
      
     
     function readCookie(name) {
index 418dc93..e48917c 100644 (file)
@@ -93,7 +93,7 @@ handlers.push({key: KEYS.ENTER,
                 //     gotoOptions = {caretTo: 'start'};
                 // }
 
-                var result = position.element.data('wlxmlNode').transform('rng.breakContent', {offset: position.offset}),
+                var result = position.element.data('wlxmlNode').breakContent({offset: position.offset}),
                     goto, gotoOptions;
                 if(result.emptyText) {
                     goto = result.createdEmpty;
diff --git a/src/editor/plugins/core/core.js b/src/editor/plugins/core/core.js
new file mode 100644 (file)
index 0000000..718a985
--- /dev/null
@@ -0,0 +1,31 @@
+define(function(require) {
+    
+'use strict';
+
+var _ = require('libs/underscore'),
+    plugin = {documentExtension: {textNode: {}}};
+
+
+plugin.documentExtension.textNode.transformations = {
+    breakContent: {
+        impl: function(args) {
+            var node = this,
+                newNodes, emptyText;
+            newNodes = node.split({offset: args.offset});
+            [newNodes.first, newNodes.second].some(function(newNode) {
+                if(!(newNode.contents().length)) {
+                    emptyText = newNode.append({text: ''});
+                    return true; // break
+                }
+            });
+            return _.extend(newNodes, {emptyText: emptyText});
+        },
+        getChangeRoot: function() {
+            return this.context.parent().parent();
+        }
+    }
+};
+
+return plugin;
+
+});
\ No newline at end of file
diff --git a/src/editor/plugins/core/core.test.js b/src/editor/plugins/core/core.test.js
new file mode 100644 (file)
index 0000000..940e22e
--- /dev/null
@@ -0,0 +1,59 @@
+define(function(require) {
+    
+'use strict';
+/* globals describe, it */
+
+var chai = require('libs/chai'),
+    wlxml = require('wlxml/wlxml'),
+    corePlugin = require('./core.js'),
+    expect = chai.expect;
+
+var getDocumentFromXML = function(xml, options) {
+    var doc = wlxml.WLXMLDocumentFromXML(xml, options || {});
+    doc.registerExtension(corePlugin.documentExtension);
+    return doc;
+};
+
+
+describe('Document extensions', function() {
+    describe('break content', function() {
+        it('break text into two nodes', function() {
+            var doc = getDocumentFromXML('<section><div>Alice</div></section>'),
+                textNode = doc.root.contents()[0].contents()[0];
+            
+            var result = textNode.breakContent({offset:3});
+
+            var section = doc.root;
+            expect(section.contents().length).to.equal(2);
+            expect(section.contents()[0].contents()[0].getText()).to.equal('Ali');
+            expect(section.contents()[1].contents()[0].getText()).to.equal('ce');
+
+            expect(result.first.sameNode(section.contents()[0])).to.equal(true);
+            expect(result.second.sameNode(section.contents()[1])).to.equal(true);
+            expect(result.emptyText).to.equal(undefined, 'no new text node created');
+        });
+        it('puts empty text node when breaking at the very beginning', function() {
+            var doc = getDocumentFromXML('<section><div>Alice</div></section>'),
+                textNode = doc.root.contents()[0].contents()[0];
+            
+            var result = textNode.breakContent({offset:0}),
+                firstNode = doc.root.contents()[0];
+
+            expect(result.emptyText.sameNode(firstNode.contents()[0]));
+            expect(result.emptyText.getText()).to.equal('');
+        });
+        it('puts empty text node when breaking at the very end', function() {
+            var doc = getDocumentFromXML('<section><div>Alice</div></section>'),
+            textNode = doc.root.contents()[0].contents()[0];
+            
+            var result = textNode.breakContent({offset:5}),
+                secondNode = doc.root.contents()[1];
+            
+            expect(result.emptyText.sameNode(secondNode.contents()[0]));
+            expect(result.emptyText.getText()).to.equal('');
+        });
+    });
+});
+
+
+});
\ No newline at end of file
index 0da2916..eeef9f9 100644 (file)
@@ -12,7 +12,8 @@ var Runner = function(app, modules) {
     var bootstrappedData = {},
         options = {},
         moduleInstances = {},
-        eventListeners = [];
+        eventListeners = [],
+        plugins = [];
         
     _.each(_.keys(modules || {}), function(moduleName) {
         if(_.contains(app.permissions[moduleName] || [], 'handleEvents')) {
@@ -53,13 +54,20 @@ var Runner = function(app, modules) {
         this.getDOM = _.contains(permissions, 'getDOM') ? function() {
             return $(options.rootSelector);
         } : undefined;
-        
+
+        this.getPlugins = function() {
+            return plugins;
+        };
     };
     
     
     this.setBootstrappedData = function(moduleName, data) {
         bootstrappedData[moduleName] = data;
     };
+
+    this.registerPlugin = function(plugin) {
+        plugins.push(plugin);
+    };
     
     this.start = function(_options) {
         options = _.extend({