Browse Source

Merge branch 'dev' into new-rte

pull/415/head
Artur Arseniev 9 years ago
parent
commit
6888cd1452
  1. 10
      .editorconfig
  2. 4
      .gitignore
  3. 4
      .npmignore
  4. 26
      README.md
  5. 4
      dist/grapes.min.js
  6. 1
      index.html
  7. 15
      package.json
  8. 2
      src/asset_manager/view/FileUploader.js
  9. 115
      src/block_manager/index.js
  10. 12
      src/block_manager/view/BlocksView.js
  11. 12
      src/commands/index.js
  12. 30
      src/commands/view/OpenBlocks.js
  13. 2
      src/editor/index.js
  14. 102
      src/styles/scss/_gjs_variables.scss
  15. 3
      test/specs/block_manager/index.js
  16. 30
      test/specs/commands/index.js
  17. 16
      test/specs/grapesjs/index.js

10
.editorconfig

@ -0,0 +1,10 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.js]
charset = utf-8
indent_style = space
indent_size = 2

4
.gitignore

@ -2,7 +2,8 @@
.settings/ .settings/
.sass-cache/ .sass-cache/
.project .project
npm-debug.log .idea
npm-debug.log*
style/.sass-cache/ style/.sass-cache/
img/ img/
@ -13,3 +14,4 @@ vendor/
coverage/ coverage/
node_modules/ node_modules/
bower_components/ bower_components/
grapesjs-*.tgz

4
.npmignore

@ -0,0 +1,4 @@
test
index.html
webpack.config.js
grapesjs-*.tgz

26
README.md

@ -1,9 +1,15 @@
# [GrapesJS](http://grapesjs.com) # [GrapesJS](http://grapesjs.com)
[![Build Status](https://travis-ci.org/artf/grapesjs.svg?branch=master)](https://travis-ci.org/artf/grapesjs) [![Build Status](https://travis-ci.org/artf/grapesjs.svg?branch=master)](https://travis-ci.org/artf/grapesjs)
[![Chat](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/QAbgGXq)
<p align="center"><img src="http://grapesjs.com/img/grapesjs-front-page-m.jpg" alt="GrapesJS" width="500" align="center"/></p> <p align="center"><img src="http://grapesjs.com/img/grapesjs-front-page-m.jpg" alt="GrapesJS" width="500" align="center"/></p>
<br/>
<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/nb9nPYf2XqCE1PbgcQj6gf4D/artf/grapesjs'>
<img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/nb9nPYf2XqCE1PbgcQj6gf4D/artf/grapesjs.svg' />
</a>
GrapesJS is a free and open source Web Builder Framework which helps you building HTML templates to be used inside sites, newsletters and mobile apps. GrapesJS is a free and open source Web Builder Framework which helps you building HTML templates to be used inside sites, newsletters and mobile apps.
Mainly GrapesJS was designed to be used inside a [CMS] to speed up a creation of dynamic templates. To better understand this concept check the image below Mainly GrapesJS was designed to be used inside a [CMS] to speed up a creation of dynamic templates. To better understand this concept check the image below
@ -32,7 +38,6 @@ Newsletter Demo - http://grapesjs.com/demo-newsletter-editor.html
* [API](#api) * [API](#api)
* [Testing](#testing) * [Testing](#testing)
* [Plugins](#plugins) * [Plugins](#plugins)
* [Sponsors](#sponsors)
* [Support](#support) * [Support](#support)
* [License](#license) * [License](#license)
@ -106,13 +111,6 @@ $ npm run build
## Usage ## Usage
JQuery is the only hard dependency so you have to include it before using GrapesJS
```html
<script src="//code.jquery.com/jquery-3.2.1.min.js"></script>
```
After that include scripts from GrapesJS with all your configurations
```html ```html
<link rel="stylesheet" href="path/to/grapes.min.css"> <link rel="stylesheet" href="path/to/grapes.min.css">
<script src="path/to/grapes.min.js"></script> <script src="path/to/grapes.min.js"></script>
@ -199,16 +197,6 @@ Find out more about plugins here: [Creating plugins](https://github.com/artf/gra
## Sponsors
The project is sponsored by
[![Sendloop](http://grapesjs.com/img/sendloop-logo-l.png)](https://sendloop.com)
## Support ## Support
If you like the project support it with a donation of your choice or become a backer/sponsor via [Open Collective](https://opencollective.com/grapesjs) If you like the project support it with a donation of your choice or become a backer/sponsor via [Open Collective](https://opencollective.com/grapesjs)

4
dist/grapes.min.js

File diff suppressed because one or more lines are too long

1
index.html

@ -4,7 +4,6 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>GrapesJS</title> <title>GrapesJS</title>
<link rel="stylesheet" href="dist/css/grapes.min.css"> <link rel="stylesheet" href="dist/css/grapes.min.css">
<!-- script src="node_modules/jquery/dist/jquery.min.js"></script -->
<script src="dist/grapes.min.js"></script> <script src="dist/grapes.min.js"></script>
</head> </head>

15
package.json

@ -1,7 +1,7 @@
{ {
"name": "grapesjs", "name": "grapesjs",
"description": "Free and Open Source Web Builder Framework", "description": "Free and Open Source Web Builder Framework",
"version": "0.11.4", "version": "0.12.5",
"author": "Artur Arseniev", "author": "Artur Arseniev",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"homepage": "http://grapesjs.com", "homepage": "http://grapesjs.com",
@ -44,18 +44,15 @@
"whatwg-fetch": "^2.0.3" "whatwg-fetch": "^2.0.3"
}, },
"keywords": [ "keywords": [
"wte",
"grapes", "grapes",
"grapesjs", "grapesjs",
"web template editor",
"web site builder",
"web template builder",
"html website builder",
"site builder",
"newsletter builder",
"wysiwyg", "wysiwyg",
"web",
"template", "template",
"editor" "editor",
"newsletter",
"site",
"builder"
], ],
"babel": { "babel": {
"presets": [ "presets": [

2
src/asset_manager/view/FileUploader.js

@ -73,7 +73,7 @@ module.exports = Backbone.View.extend({
const em = this.config.em; const em = this.config.em;
const config = this.config; const config = this.config;
const target = this.target; const target = this.target;
const json = typeof text === 'text' ? JSON.parse(text) : text; const json = typeof text === 'string' ? JSON.parse(text) : text;
em && em.trigger('asset:upload:response', json); em && em.trigger('asset:upload:response', json);
if (config.autoAdd && target) { if (config.autoAdd && target) {

115
src/block_manager/index.js

@ -2,7 +2,9 @@
* * [add](#add) * * [add](#add)
* * [get](#get) * * [get](#get)
* * [getAll](#getall) * * [getAll](#getall)
* * [getAllVisible](#getallvisible)
* * [getCategories](#getcategories) * * [getCategories](#getcategories)
* * [getContainer](#getcontainer)
* * [render](#render) * * [render](#render)
* *
* Block manager helps managing various, draggable, piece of contents that could be easily reused inside templates. * Block manager helps managing various, draggable, piece of contents that could be easily reused inside templates.
@ -32,7 +34,7 @@ module.exports = () => {
Blocks = require('./model/Blocks'), Blocks = require('./model/Blocks'),
BlockCategories = require('./model/Categories'), BlockCategories = require('./model/Categories'),
BlocksView = require('./view/BlocksView'); BlocksView = require('./view/BlocksView');
var blocks, view; var blocks, blocksVisible, blocksView;
var categories = []; var categories = [];
return { return {
@ -52,19 +54,58 @@ module.exports = () => {
*/ */
init(config) { init(config) {
c = config || {}; c = config || {};
for (var name in defaults) { const em = c.em;
if (!(name in c))
for (let name in defaults) {
if (!(name in c)) {
c[name] = defaults[name]; c[name] = defaults[name];
}
} }
blocks = new Blocks(c.blocks);
// Global blocks collection
blocks = new Blocks([]);
blocksVisible = new Blocks([]);
categories = new BlockCategories(), categories = new BlockCategories(),
view = new BlocksView({ blocksView = new BlocksView({
collection: blocks, // Visible collection
collection: blocksVisible,
categories, categories,
}, c); }, c);
// Setup the sync between the global and public collections
blocks.listenTo(blocks, 'add', model => {
blocksVisible.add(model);
em && em.trigger('block:add', model);
});
blocks.listenTo(blocks, 'remove', model => {
blocksVisible.remove(model);
em && em.trigger('block:remove', model);
});
blocks.listenTo(blocks, 'reset', coll => {
blocksVisible.reset(coll.models);
});
return this; return this;
}, },
/**
* Get configuration object
* @return {Object}
*/
getConfig() {
return c;
},
/**
* Load default blocks if the collection is empty
*/
onLoad() {
const blocks = this.getAll();
!blocks.length && blocks.reset(c.blocks);
},
/** /**
* Add new block to the collection. * Add new block to the collection.
* @param {string} id Block id * @param {string} id Block id
@ -98,7 +139,7 @@ module.exports = () => {
* Return the block by id * Return the block by id
* @param {string} id Block id * @param {string} id Block id
* @example * @example
* var block = blockManager.get('h1-block'); * const block = blockManager.get('h1-block');
* console.log(JSON.stringify(block)); * console.log(JSON.stringify(block));
* // {label: 'Heading', content: '<h1>Put your ...', ...} * // {label: 'Heading', content: '<h1>Put your ...', ...}
*/ */
@ -110,7 +151,7 @@ module.exports = () => {
* Return all blocks * Return all blocks
* @return {Collection} * @return {Collection}
* @example * @example
* var blocks = blockManager.getAll(); * const blocks = blockManager.getAll();
* console.log(JSON.stringify(blocks)); * console.log(JSON.stringify(blocks));
* // [{label: 'Heading', content: '<h1>Put your ...'}, ...] * // [{label: 'Heading', content: '<h1>Put your ...'}, ...]
*/ */
@ -118,9 +159,26 @@ module.exports = () => {
return blocks; return blocks;
}, },
/**
* Return the visible collection, which containes blocks actually rendered
* @return {Collection}
*/
getAllVisible() {
return blocksVisible;
},
/**
* Remove a block by id
* @param {string} id Block id
* @return {Block} Removed block
*/
remove(id) {
return blocks.remove(id);
},
/** /**
* Get all available categories. * Get all available categories.
* Is possible to add categories only with blocks via 'add()' method * It's possible to add categories only within blocks via 'add()' method
* @return {Array|Collection} * @return {Array|Collection}
*/ */
getCategories() { getCategories() {
@ -128,20 +186,43 @@ module.exports = () => {
}, },
/** /**
* Render blocks * Return the Blocks container element
* @return {HTMLElement} * @return {HTMLElement}
*/ */
render() { getContainer() {
return view.render().el; return blocksView.el;
}, },
/** /**
* Remove block by id * Render blocks
* @param {string} id Block id * @param {Array} blocks Blocks to render, without the argument will render
* @return {Block} Removed block * all global blocks
* @example
* // Render all blocks (inside the global collection)
* blockManager.render();
*
* // Render new set of blocks
* const blocks = blockManager.getAll();
* blockManager.render(blocks.filter(
* block => block.get('category') == 'sections'
* ));
* // Or a new set from an array
* blockManager.render([
* {label: 'Label text', content: '<div>Content</div>'}
* ]);
*
* // Back to blocks from the global collection
* blockManager.render();
*/ */
remove(id) { render(blocks) {
return blocks.remove(id); const toRender = blocks || this.getAll().models;
if (!blocksView.rendered) {
blocksView.render();
blocksView.rendered = 1;
}
blocksView.collection.reset(toRender);
}, },
}; };

12
src/block_manager/view/BlocksView.js

@ -14,7 +14,9 @@ module.exports = Backbone.View.extend({
this.noCatClass = `${ppfx}blocks-no-cat`; this.noCatClass = `${ppfx}blocks-no-cat`;
this.blockContClass = `${ppfx}blocks-c`; this.blockContClass = `${ppfx}blocks-c`;
this.catsClass = `${ppfx}block-categories`; this.catsClass = `${ppfx}block-categories`;
this.listenTo(this.collection, 'add', this.addTo); const coll = this.collection;
this.listenTo(coll, 'add', this.addTo);
this.listenTo(coll, 'reset', this.render);
this.em = this.config.em; this.em = this.config.em;
this.tac = 'test-tac'; this.tac = 'test-tac';
this.grabbingCls = this.ppfx + 'grabbing'; this.grabbingCls = this.ppfx + 'grabbing';
@ -167,8 +169,7 @@ module.exports = Backbone.View.extend({
}, },
render() { render() {
var ppfx = this.ppfx; const frag = document.createDocumentFragment();
var frag = document.createDocumentFragment();
this.catsEl = null; this.catsEl = null;
this.blocksEl = null; this.blocksEl = null;
this.renderedCategories = []; this.renderedCategories = [];
@ -179,10 +180,7 @@ module.exports = Backbone.View.extend({
</div> </div>
`; `;
this.collection.each(function(model){ this.collection.each(model => this.add(model, frag));
this.add(model, frag);
}, this);
this.append(frag); this.append(frag);
this.$el.addClass(this.blockContClass + 's') this.$el.addClass(this.blockContClass + 's')
return this; return this;

12
src/commands/index.js

@ -196,15 +196,9 @@ module.exports = () => {
if(c.em) if(c.em)
c.model = c.em.get('Canvas'); c.model = c.em.get('Canvas');
return this; this.loadDefaultCommands()
},
/** return this;
* On load callback
* @private
*/
onLoad() {
this.loadDefaultCommands();
}, },
/** /**
@ -258,7 +252,7 @@ module.exports = () => {
* */ * */
loadDefaultCommands() { loadDefaultCommands() {
for (var id in defaultCommands) { for (var id in defaultCommands) {
this.add(id, defaultCommands[id]); this.add(id, defaultCommands[id]);
} }
return this; return this;

30
src/commands/view/OpenBlocks.js

@ -1,28 +1,24 @@
const $ = Backbone.$;
module.exports = { module.exports = {
run(editor, sender) { run(editor, sender) {
var config = editor.Config; const bm = editor.BlockManager;
var pfx = config.stylePrefix; const pn = editor.Panels;
var bm = editor.BlockManager;
var panelC; if (!this.blocks) {
if(!this.blocks){ bm.render();
this.blocks = $('<div></div>').get(0); const id = 'views-container';
this.blocks.appendChild(bm.render()); const blocks = document.createElement('div');
var panels = editor.Panels; const panels = pn.getPanel(id) || pn.addPanel({id});
if(!panels.getPanel('views-container')) blocks.appendChild(bm.getContainer());
panelC = panels.addPanel({id: 'views-container'}); panels.set('appendContent', blocks).trigger('change:appendContent');
else this.blocks = blocks;
panelC = panels.getPanel('views-container');
panelC.set('appendContent', this.blocks).trigger('change:appendContent');
} }
this.blocks.style.display = 'block'; this.blocks.style.display = 'block';
}, },
stop() { stop() {
if(this.blocks) const blocks = this.blocks;
this.blocks.style.display = 'none'; blocks && (blocks.style.display = 'none');
} }
}; };

2
src/editor/index.js

@ -38,6 +38,8 @@
* * `component:styleUpdate` - Triggered when the style of the component is updated * * `component:styleUpdate` - Triggered when the style of the component is updated
* * `component:styleUpdate:{propertyName}` - Listen for a specific style property change * * `component:styleUpdate:{propertyName}` - Listen for a specific style property change
* * `component:selected` - New component selected * * `component:selected` - New component selected
* * `block:add` - New block added
* * `block:remove` - Block removed
* * `asset:add` - New asset added * * `asset:add` - New asset added
* * `asset:remove` - Asset removed * * `asset:remove` - Asset removed
* * `asset:upload:start` - Before the upload is started * * `asset:upload:start` - Before the upload is started

102
src/styles/scss/_gjs_variables.scss

@ -1,78 +1,76 @@
/* Class names prefixes */ /* Class names prefixes */
$app-prefix: 'gjs-' !default; $app-prefix: 'gjs-' !default;
$nv-prefix: $app-prefix + 'nv-' !default; $nv-prefix: $app-prefix + 'nv-' !default;
$rte-prefix: $app-prefix + 'rte-' !default; $rte-prefix: $app-prefix + 'rte-' !default;
$comp-prefix: $app-prefix + 'comp-' !default; $comp-prefix: $app-prefix + 'comp-' !default;
$mdl-prefix: $app-prefix + 'mdl-' !default; $mdl-prefix: $app-prefix + 'mdl-' !default;
$am-prefix: $app-prefix + 'am-' !default; $am-prefix: $app-prefix + 'am-' !default;
$cm-prefix: $app-prefix + 'cm-' !default; $cm-prefix: $app-prefix + 'cm-' !default;
$pn-prefix: $app-prefix + 'pn-' !default; $pn-prefix: $app-prefix + 'pn-' !default;
$com-prefix: $app-prefix + 'com-' !default; $com-prefix: $app-prefix + 'com-' !default;
$sm-prefix: $app-prefix + 'sm-' !default; $sm-prefix: $app-prefix + 'sm-' !default;
$cv-prefix: $app-prefix + 'cv-' !default; $cv-prefix: $app-prefix + 'cv-' !default;
$clm-prefix: $app-prefix + 'clm-' !default; $clm-prefix: $app-prefix + 'clm-' !default;
$trt-prefix: $app-prefix + 'trt-' !default; $trt-prefix: $app-prefix + 'trt-' !default;
/* Colors / Theme */ /* Colors / Theme */
/* Dark theme */ /* Dark theme */
$mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-gradient(top, #fca99b 0%, #6e2842 100%) */ $mainColor: #444 !default; /* Light: #573454 Dark: #3b2639 -moz-linear-gradient(top, #fca99b 0%, #6e2842 100%) */
$fontColor: #ddd !default; /* l: #d8d7db */ $fontColor: #ddd !default; /* l: #d8d7db */
$fontColorActive: #f8f8f8 !default; $fontColorActive: #f8f8f8 !default;
/* Light theme /* Light theme
$mainColor: #fff; $mainColor: #fff;
$fontColor: #9299a3; $fontColor: #9299a3;
$fontColorActive: #4f8ef7; $fontColorActive: #4f8ef7;
*/ */
$mainDkColor: rgba(0, 0, 0, 0.2) !default;/* darken($mainColor, 4%) - #383838 */ $mainDkColor: rgba(0, 0, 0, 0.2) !default;/* darken($mainColor, 4%) - #383838 */
$mainDklColor: rgba(0, 0, 0, 0.1) !default; $mainDklColor: rgba(0, 0, 0, 0.1) !default;
$mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */ $mainLhColor: rgba(255, 255, 255, 0.1) !default; /* #515151 */
$mainLhlColor: rgba(255, 255, 255, 0.7) !default; $mainLhlColor: rgba(255, 255, 255, 0.7) !default;
$fontColorDk: #777 !default; $fontColorDk: #777 !default;
$mainFont: Helvetica, sans-serif !default; $mainFont: Helvetica, sans-serif !default;
$colorBlue: #3b97e3 !default; $colorBlue: #3b97e3 !default;
$colorRed: #dd3636 !default; $colorRed: #dd3636 !default;
$colorYell: #ffca6f !default; $colorYell: #ffca6f !default;
$colorGreen: #62c462 !default; $colorGreen: #62c462 !default;
$tagBg: #804f7b !default; $tagBg: #804f7b !default;
$secColor: $tagBg !default; $secColor: $tagBg !default;
$imageCompDim: 50px !default; $imageCompDim: 50px !default;
$leftWidth: 15% !default; $leftWidth: 15% !default;
/* Color Helpers */ /* Color Helpers */
$colorHighlight: #71b7f1 !default; $colorHighlight: #71b7f1 !default;
$colorWarn: #ffca6f !default; $colorWarn: #ffca6f !default;
/* Canvas */ /* Canvas */
$hndlMargin: -5px !default; $hndlMargin: -5px !default;
/* Components / Inputs */ /* Components / Inputs */
$lightBorder: rgba(255, 255, 255, 0.05) !default; $lightBorder: rgba(255, 255, 255, 0.05) !default;
$inputFontColor: $mainLhlColor !default; /* #d5d5d5 */ $inputFontColor: $mainLhlColor !default; /* #d5d5d5 */
$arrowColor: $mainLhlColor !default; /* b1b1b1 */ $arrowColor: $mainLhlColor !default; /* b1b1b1 */
$darkTextShadow: $mainDkColor !default; /* #252525 */ $darkTextShadow: $mainDkColor !default; /* #252525 */
$darkBorder: rgba(0, 0, 0, 0.15) !default; /* 303030 */ $darkBorder: rgba(0, 0, 0, 0.15) !default; /* 303030 */
$colorpSize: 22px !default; $colorpSize: 22px !default;
$inputPadding: 5px !default; // Has to be a single value $inputPadding: 5px !default; // Has to be a single value
/* Class manager */ /* Class manager */
$addBtnBg: lighten($mainDkColor, 10%) !default; $addBtnBg: lighten($mainDkColor, 10%) !default;
$paddElClm: 5px 6px !default; $paddElClm: 5px 6px !default;
/* File uploader */ /* File uploader */
$uploadPadding: 150px 10px !default; $uploadPadding: 150px 10px !default;
/* Commands */ /* Commands */
$animSpeed: 0.2s !default; $animSpeed: 0.2s !default;
/* Fonts */ /* Fonts */
$fontPath: '../fonts' !default; $fontPath: '../fonts' !default;
$fontName: 'main-fonts' !default; $fontName: 'main-fonts' !default;
$fontV: 20 !default;//random(1000) $fontV: 20 !default;//random(1000)

3
test/specs/block_manager/index.js

@ -65,7 +65,8 @@ describe('BlockManager', () => {
}); });
it('Render blocks', () => { it('Render blocks', () => {
expect(obj.render()).toExist(); obj.render();
expect(obj.getContainer()).toExist();
}); });
}); });

30
test/specs/commands/index.js

@ -25,8 +25,30 @@ describe('Commands', () => {
expect(obj.get('test').test).toEqual('test'); expect(obj.get('test').test).toEqual('test');
}); });
it('No default commands at init', () => { it('Load default commands at init', () => {
expect(obj.get('select-comp')).toEqual(null); expect(obj.get('select-comp')).toNotEqual(null);
expect(obj.get('create-comp')).toNotEqual(null);
expect(obj.get('delete-comp')).toNotEqual(null);
expect(obj.get('image-comp')).toNotEqual(null);
expect(obj.get('move-comp')).toNotEqual(null);
expect(obj.get('text-comp')).toNotEqual(null);
expect(obj.get('insert-custom')).toNotEqual(null);
expect(obj.get('export-template')).toNotEqual(null);
expect(obj.get('sw-visibility')).toNotEqual(null);
expect(obj.get('open-layers')).toNotEqual(null);
expect(obj.get('open-sm')).toNotEqual(null);
expect(obj.get('open-tm')).toNotEqual(null);
expect(obj.get('open-blocks')).toNotEqual(null);
expect(obj.get('open-assets')).toNotEqual(null);
expect(obj.get('show-offset')).toNotEqual(null);
expect(obj.get('select-parent')).toNotEqual(null);
expect(obj.get('tlb-delete')).toNotEqual(null);
expect(obj.get('tlb-clone')).toNotEqual(null);
expect(obj.get('tlb-move')).toNotEqual(null);
expect(obj.get('fullscreen')).toNotEqual(null);
expect(obj.get('preview')).toNotEqual(null);
expect(obj.get('resize')).toNotEqual(null);
expect(obj.get('drag')).toNotEqual(null);
}); });
it('Default commands after loadDefaultCommands', () => { it('Default commands after loadDefaultCommands', () => {
@ -34,6 +56,10 @@ describe('Commands', () => {
expect(obj.get('select-comp')).toNotEqual(null); expect(obj.get('select-comp')).toNotEqual(null);
}); });
it('Commands module should not have toLoad property', () => {
expect(obj.toLoad).toEqual(null);
});
}); });
}); });

16
test/specs/grapesjs/index.js

@ -230,6 +230,22 @@ describe('GrapesJS', () => {
expect(editor.getDevice()).toEqual('Tablet'); expect(editor.getDevice()).toEqual('Tablet');
}); });
// Problems with iframe loading
it.skip('Init new editor with custom plugin overrides default commands', () => {
var editor,
pluginName = 'test-plugin-opts';
obj.plugins.add(pluginName, (edt, opts) => {
let cmdm = edt.Commands;
// Overwrite export template
cmdm.add('export-template', {test: 1});
});
config.plugins = [pluginName];
editor = obj.init(config);
expect(editor.Commands.get('export-template').test).toEqual(1);
});
}); });
}); });

Loading…
Cancel
Save