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/
.sass-cache/
.project
npm-debug.log
.idea
npm-debug.log*
style/.sass-cache/
img/
@ -13,3 +14,4 @@ vendor/
coverage/
node_modules/
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)
[![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>
<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.
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)
* [Testing](#testing)
* [Plugins](#plugins)
* [Sponsors](#sponsors)
* [Support](#support)
* [License](#license)
@ -106,13 +111,6 @@ $ npm run build
## 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
<link rel="stylesheet" href="path/to/grapes.min.css">
<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
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">
<title>GrapesJS</title>
<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>
</head>

15
package.json

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

2
src/asset_manager/view/FileUploader.js

@ -73,7 +73,7 @@ module.exports = Backbone.View.extend({
const em = this.config.em;
const config = this.config;
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);
if (config.autoAdd && target) {

115
src/block_manager/index.js

@ -2,7 +2,9 @@
* * [add](#add)
* * [get](#get)
* * [getAll](#getall)
* * [getAllVisible](#getallvisible)
* * [getCategories](#getcategories)
* * [getContainer](#getcontainer)
* * [render](#render)
*
* 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'),
BlockCategories = require('./model/Categories'),
BlocksView = require('./view/BlocksView');
var blocks, view;
var blocks, blocksVisible, blocksView;
var categories = [];
return {
@ -52,19 +54,58 @@ module.exports = () => {
*/
init(config) {
c = config || {};
for (var name in defaults) {
if (!(name in c))
const em = c.em;
for (let name in defaults) {
if (!(name in c)) {
c[name] = defaults[name];
}
}
blocks = new Blocks(c.blocks);
// Global blocks collection
blocks = new Blocks([]);
blocksVisible = new Blocks([]);
categories = new BlockCategories(),
view = new BlocksView({
collection: blocks,
blocksView = new BlocksView({
// Visible collection
collection: blocksVisible,
categories,
}, 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;
},
/**
* 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.
* @param {string} id Block id
@ -98,7 +139,7 @@ module.exports = () => {
* Return the block by id
* @param {string} id Block id
* @example
* var block = blockManager.get('h1-block');
* const block = blockManager.get('h1-block');
* console.log(JSON.stringify(block));
* // {label: 'Heading', content: '<h1>Put your ...', ...}
*/
@ -110,7 +151,7 @@ module.exports = () => {
* Return all blocks
* @return {Collection}
* @example
* var blocks = blockManager.getAll();
* const blocks = blockManager.getAll();
* console.log(JSON.stringify(blocks));
* // [{label: 'Heading', content: '<h1>Put your ...'}, ...]
*/
@ -118,9 +159,26 @@ module.exports = () => {
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.
* 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}
*/
getCategories() {
@ -128,20 +186,43 @@ module.exports = () => {
},
/**
* Render blocks
* Return the Blocks container element
* @return {HTMLElement}
*/
render() {
return view.render().el;
getContainer() {
return blocksView.el;
},
/**
* Remove block by id
* @param {string} id Block id
* @return {Block} Removed block
* Render blocks
* @param {Array} blocks Blocks to render, without the argument will render
* 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) {
return blocks.remove(id);
render(blocks) {
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.blockContClass = `${ppfx}blocks-c`;
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.tac = 'test-tac';
this.grabbingCls = this.ppfx + 'grabbing';
@ -167,8 +169,7 @@ module.exports = Backbone.View.extend({
},
render() {
var ppfx = this.ppfx;
var frag = document.createDocumentFragment();
const frag = document.createDocumentFragment();
this.catsEl = null;
this.blocksEl = null;
this.renderedCategories = [];
@ -179,10 +180,7 @@ module.exports = Backbone.View.extend({
</div>
`;
this.collection.each(function(model){
this.add(model, frag);
}, this);
this.collection.each(model => this.add(model, frag));
this.append(frag);
this.$el.addClass(this.blockContClass + 's')
return this;

12
src/commands/index.js

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

30
src/commands/view/OpenBlocks.js

@ -1,28 +1,24 @@
const $ = Backbone.$;
module.exports = {
run(editor, sender) {
var config = editor.Config;
var pfx = config.stylePrefix;
var bm = editor.BlockManager;
var panelC;
if(!this.blocks){
this.blocks = $('<div></div>').get(0);
this.blocks.appendChild(bm.render());
var panels = editor.Panels;
if(!panels.getPanel('views-container'))
panelC = panels.addPanel({id: 'views-container'});
else
panelC = panels.getPanel('views-container');
panelC.set('appendContent', this.blocks).trigger('change:appendContent');
const bm = editor.BlockManager;
const pn = editor.Panels;
if (!this.blocks) {
bm.render();
const id = 'views-container';
const blocks = document.createElement('div');
const panels = pn.getPanel(id) || pn.addPanel({id});
blocks.appendChild(bm.getContainer());
panels.set('appendContent', blocks).trigger('change:appendContent');
this.blocks = blocks;
}
this.blocks.style.display = 'block';
},
stop() {
if(this.blocks)
this.blocks.style.display = 'none';
const blocks = this.blocks;
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:{propertyName}` - Listen for a specific style property change
* * `component:selected` - New component selected
* * `block:add` - New block added
* * `block:remove` - Block removed
* * `asset:add` - New asset added
* * `asset:remove` - Asset removed
* * `asset:upload:start` - Before the upload is started

102
src/styles/scss/_gjs_variables.scss

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

3
test/specs/block_manager/index.js

@ -65,7 +65,8 @@ describe('BlockManager', () => {
});
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');
});
it('No default commands at init', () => {
expect(obj.get('select-comp')).toEqual(null);
it('Load default commands at init', () => {
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', () => {
@ -34,6 +56,10 @@ describe('Commands', () => {
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');
});
// 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