├── .gitignore ├── LICENSE ├── README.txt ├── custom_icons ├── expressions-icon.svg └── storage-icon.svg ├── dist ├── grapesjs-mavo.min.css └── grapesjs-mavo.min.js ├── expressions.json ├── grapesjs ├── .editorconfig ├── .eslintrc ├── .github │ ├── ISSUE_TEMPLATE.md │ └── no-response.yml ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── dist │ ├── css │ │ └── grapes.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── fontawesome-webfont.woff2 │ │ ├── main-fonts.eot │ │ ├── main-fonts.svg │ │ ├── main-fonts.ttf │ │ └── main-fonts.woff │ ├── grapes.js │ └── grapes.min.js ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── asset_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Asset.js │ │ │ ├── AssetImage.js │ │ │ └── Assets.js │ │ └── view │ │ │ ├── AssetImageView.js │ │ │ ├── AssetView.js │ │ │ ├── AssetsView.js │ │ │ └── FileUploader.js │ ├── block_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Block.js │ │ │ ├── Blocks.js │ │ │ ├── Categories.js │ │ │ └── Category.js │ │ └── view │ │ │ ├── BlockView.js │ │ │ ├── BlocksView.js │ │ │ └── CategoryView.js │ ├── canvas │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Canvas.js │ │ │ └── Frame.js │ │ └── view │ │ │ ├── CanvasView.js │ │ │ └── FrameView.js │ ├── code_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── CodeMirrorEditor.js │ │ │ ├── CssGenerator.js │ │ │ ├── HtmlGenerator.js │ │ │ ├── JsGenerator.js │ │ │ └── JsonGenerator.js │ │ └── view │ │ │ └── EditorView.js │ ├── commands │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Command.js │ │ │ └── Commands.js │ │ └── view │ │ │ ├── CommandAbstract.js │ │ │ ├── CreateComponent.js │ │ │ ├── DeleteComponent.js │ │ │ ├── Drag.js │ │ │ ├── ExportTemplate.js │ │ │ ├── Fullscreen.js │ │ │ ├── ImageComponent.js │ │ │ ├── InsertCustom.js │ │ │ ├── MoveComponent.js │ │ │ ├── OpenAssets.js │ │ │ ├── OpenBlocks.js │ │ │ ├── OpenLayers.js │ │ │ ├── OpenStyleManager.js │ │ │ ├── OpenTraitManager.js │ │ │ ├── Preview.js │ │ │ ├── Resize.js │ │ │ ├── SelectComponent.js │ │ │ ├── SelectParent.js │ │ │ ├── SelectPosition.js │ │ │ ├── ShowOffset.js │ │ │ ├── SwitchVisibility.js │ │ │ └── TextComponent.js │ ├── css_composer │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── CssRule.js │ │ │ └── CssRules.js │ │ └── view │ │ │ ├── CssGroupRuleView.js │ │ │ ├── CssRuleView.js │ │ │ └── CssRulesView.js │ ├── device_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Device.js │ │ │ └── Devices.js │ │ └── view │ │ │ └── DevicesView.js │ ├── dom_components │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Component.js │ │ │ ├── ComponentImage.js │ │ │ ├── ComponentLink.js │ │ │ ├── ComponentMap.js │ │ │ ├── ComponentScript.js │ │ │ ├── ComponentSvg.js │ │ │ ├── ComponentTable.js │ │ │ ├── ComponentTableBody.js │ │ │ ├── ComponentTableCell.js │ │ │ ├── ComponentTableFoot.js │ │ │ ├── ComponentTableHead.js │ │ │ ├── ComponentTableRow.js │ │ │ ├── ComponentText.js │ │ │ ├── ComponentTextNode.js │ │ │ ├── ComponentVideo.js │ │ │ ├── Components.js │ │ │ ├── Toolbar.js │ │ │ └── ToolbarButton.js │ │ └── view │ │ │ ├── ComponentImageView.js │ │ │ ├── ComponentLinkView.js │ │ │ ├── ComponentMapView.js │ │ │ ├── ComponentScriptView.js │ │ │ ├── ComponentSvgView.js │ │ │ ├── ComponentTableBodyView.js │ │ │ ├── ComponentTableCellView.js │ │ │ ├── ComponentTableFootView.js │ │ │ ├── ComponentTableHeadView.js │ │ │ ├── ComponentTableRowView.js │ │ │ ├── ComponentTableView.js │ │ │ ├── ComponentTextNodeView.js │ │ │ ├── ComponentTextView.js │ │ │ ├── ComponentVideoView.js │ │ │ ├── ComponentView.js │ │ │ ├── ComponentsView.js │ │ │ ├── ToolbarButtonView.js │ │ │ └── ToolbarView.js │ ├── domain_abstract │ │ ├── model │ │ │ ├── Styleable.js │ │ │ └── TypeableCollection.js │ │ ├── ui │ │ │ ├── Input.js │ │ │ ├── InputColor.js │ │ │ └── InputNumber.js │ │ └── view │ │ │ └── DomainViews.js │ ├── editor │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ └── Editor.js │ │ └── view │ │ │ └── EditorView.js │ ├── index.js │ ├── keymaps │ │ └── index.js │ ├── modal_dialog │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ └── Modal.js │ │ └── view │ │ │ └── ModalView.js │ ├── navigator │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ └── view │ │ │ ├── ItemView.js │ │ │ └── ItemsView.js │ ├── panels │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Button.js │ │ │ ├── Buttons.js │ │ │ ├── Panel.js │ │ │ └── Panels.js │ │ └── view │ │ │ ├── ButtonView.js │ │ │ ├── ButtonsView.js │ │ │ ├── PanelView.js │ │ │ └── PanelsView.js │ ├── parser │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ └── model │ │ │ ├── ParserCss.js │ │ │ └── ParserHtml.js │ ├── plugin_manager │ │ ├── config │ │ │ └── config.js │ │ └── index.js │ ├── rich_text_editor │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ └── model │ │ │ └── RichTextEditor.js │ ├── selector_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Selector.js │ │ │ └── Selectors.js │ │ └── view │ │ │ ├── ClassTagView.js │ │ │ └── ClassTagsView.js │ ├── storage_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ └── model │ │ │ ├── LocalStorage.js │ │ │ └── RemoteStorage.js │ ├── style_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Layer.js │ │ │ ├── Layers.js │ │ │ ├── Properties.js │ │ │ ├── Property.js │ │ │ ├── PropertyComposite.js │ │ │ ├── PropertyFactory.js │ │ │ ├── PropertyInteger.js │ │ │ ├── PropertyRadio.js │ │ │ ├── PropertySlider.js │ │ │ ├── PropertyStack.js │ │ │ ├── Sector.js │ │ │ └── Sectors.js │ │ └── view │ │ │ ├── LayerView.js │ │ │ ├── LayersView.js │ │ │ ├── PropertiesView.js │ │ │ ├── PropertyColorView.js │ │ │ ├── PropertyCompositeView.js │ │ │ ├── PropertyFileView.js │ │ │ ├── PropertyIntegerView.js │ │ │ ├── PropertyRadioView.js │ │ │ ├── PropertySelectView.js │ │ │ ├── PropertySliderView.js │ │ │ ├── PropertyStackView.js │ │ │ ├── PropertyView.js │ │ │ ├── SectorView.js │ │ │ └── SectorsView.js │ ├── styles │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── fontawesome-webfont.woff2 │ │ │ ├── main-fonts.eot │ │ │ ├── main-fonts.svg │ │ │ ├── main-fonts.ttf │ │ │ └── main-fonts.woff │ │ └── scss │ │ │ ├── _gjs_assets.scss │ │ │ ├── _gjs_blocks.scss │ │ │ ├── _gjs_canvas.scss │ │ │ ├── _gjs_devices.scss │ │ │ ├── _gjs_inputs.scss │ │ │ ├── _gjs_layers.scss │ │ │ ├── _gjs_modal.scss │ │ │ ├── _gjs_panels.scss │ │ │ ├── _gjs_rte.scss │ │ │ ├── _gjs_selectors.scss │ │ │ ├── _gjs_style_manager.scss │ │ │ ├── _gjs_traits.scss │ │ │ ├── _gjs_variables.scss │ │ │ └── main.scss │ ├── trait_manager │ │ ├── config │ │ │ └── config.js │ │ ├── index.js │ │ ├── model │ │ │ ├── Trait.js │ │ │ ├── TraitFactory.js │ │ │ └── Traits.js │ │ └── view │ │ │ ├── TraitCheckboxView.js │ │ │ ├── TraitColorView.js │ │ │ ├── TraitNumberView.js │ │ │ ├── TraitSelectView.js │ │ │ ├── TraitView.js │ │ │ └── TraitsView.js │ ├── undo_manager │ │ └── index.js │ └── utils │ │ ├── ColorPicker.js │ │ ├── Dragger.js │ │ ├── Droppable.js │ │ ├── Resizer.js │ │ ├── Sorter.js │ │ ├── extender.js │ │ ├── fetch.js │ │ ├── index.js │ │ ├── mixins.js │ │ └── polyfills.js ├── test │ ├── helper.js │ ├── main.js │ └── specs │ │ ├── asset_manager │ │ ├── index.js │ │ ├── model │ │ │ ├── Asset.js │ │ │ ├── AssetImage.js │ │ │ └── Assets.js │ │ └── view │ │ │ ├── AssetImageView.js │ │ │ ├── AssetView.js │ │ │ ├── AssetsView.js │ │ │ └── FileUploader.js │ │ ├── block_manager │ │ ├── index.js │ │ └── view │ │ │ └── BlocksView.js │ │ ├── code_manager │ │ ├── index.js │ │ └── model │ │ │ └── CodeModels.js │ │ ├── commands │ │ ├── index.js │ │ ├── model │ │ │ └── CommandModels.js │ │ └── view │ │ │ └── CommandAbstract.js │ │ ├── css_composer │ │ ├── e2e │ │ │ └── CssComposer.js │ │ ├── index.js │ │ ├── model │ │ │ └── CssModels.js │ │ └── view │ │ │ ├── CssRuleView.js │ │ │ └── CssRulesView.js │ │ ├── device_manager │ │ ├── index.js │ │ └── view │ │ │ └── DevicesView.js │ │ ├── dom_components │ │ ├── index.js │ │ ├── model │ │ │ └── Component.js │ │ └── view │ │ │ ├── ComponentImageView.js │ │ │ ├── ComponentTextView.js │ │ │ ├── ComponentV.js │ │ │ └── ComponentsView.js │ │ ├── grapesjs │ │ └── index.js │ │ ├── keymaps │ │ └── index.js │ │ ├── modal │ │ ├── index.js │ │ └── view │ │ │ └── ModalView.js │ │ ├── panels │ │ ├── e2e │ │ │ └── PanelsE2e.js │ │ ├── index.js │ │ ├── model │ │ │ └── PanelModels.js │ │ └── view │ │ │ ├── ButtonView.js │ │ │ ├── ButtonsView.js │ │ │ ├── PanelView.js │ │ │ └── PanelsView.js │ │ ├── parser │ │ ├── index.js │ │ └── model │ │ │ ├── ParserCss.js │ │ │ └── ParserHtml.js │ │ ├── plugin_manager │ │ └── index.js │ │ ├── selector_manager │ │ ├── e2e │ │ │ └── ClassManager.js │ │ ├── index.js │ │ ├── model │ │ │ └── SelectorModels.js │ │ └── view │ │ │ ├── ClassTagView.js │ │ │ └── ClassTagsView.js │ │ ├── storage_manager │ │ ├── index.js │ │ └── model │ │ │ └── Models.js │ │ ├── style_manager │ │ ├── index.js │ │ ├── model │ │ │ └── Models.js │ │ └── view │ │ │ ├── LayerView.js │ │ │ ├── PropertyColorView.js │ │ │ ├── PropertyCompositeView.js │ │ │ ├── PropertyIntegerView.js │ │ │ ├── PropertyRadioView.js │ │ │ ├── PropertySelectView.js │ │ │ ├── PropertyStackView.js │ │ │ ├── PropertyView.js │ │ │ ├── SectorView.js │ │ │ └── SectorsView.js │ │ ├── test_utils.js │ │ ├── trait_manager │ │ ├── index.js │ │ ├── model │ │ │ └── TraitsModel.js │ │ └── view │ │ │ └── TraitsView.js │ │ └── utils │ │ ├── Sorter.js │ │ └── main.js └── webpack.config.js ├── index.css ├── index.html ├── index.js ├── logo.svg ├── package-lock.json ├── package.json ├── src ├── blocks │ └── index.js ├── commands │ ├── index.js │ └── openImport.js ├── components │ └── index.js ├── consts.js ├── index.js ├── panels │ └── index.js ├── style │ ├── _variables.scss │ └── main.scss ├── styles │ └── index.js └── traits │ └── index.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | private/ 4 | .eslintrc 5 | *.log 6 | _index.html 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, (YOUR NAME) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "GrapesJS" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | README -------------------------------------------------------------------------------- /custom_icons/storage-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dist/grapesjs-mavo.min.css: -------------------------------------------------------------------------------- 1 | .gjs-one-bg{background-color:#463a3c}.gjs-one-color{color:#463a3c}.gjs-one-color-h:hover{color:#463a3c}.gjs-two-bg{background-color:#b9a5a6}.gjs-two-color{color:#b9a5a6}.gjs-two-color-h:hover{color:#b9a5a6}.gjs-three-bg{background-color:#804f7b}.gjs-three-color{color:#804f7b}.gjs-three-color-h:hover{color:#804f7b}.gjs-four-bg{background-color:#d97aa6}.gjs-four-color{color:#d97aa6}.gjs-four-color-h:hover{color:#d97aa6} 2 | -------------------------------------------------------------------------------- /grapesjs/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.js] 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 2 11 | -------------------------------------------------------------------------------- /grapesjs/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "parserOptions": { 7 | "sourceType": "module", 8 | "ecmaFeatures": { 9 | "experimentalObjectRestSpread": true 10 | } 11 | }, 12 | "rules": { 13 | "strict": 0, 14 | "quotes": [0, "single"], 15 | "eol-last": [0], 16 | "no-mixed-requires": [0], 17 | "no-underscore-dangle": [0] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /grapesjs/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## WARNING 2 | READ and FOLLOW next 5 steps, then REMOVE them before posting the issue 3 | 4 | 1. Follow CONTRIBUTING Guidelines https://github.com/artf/grapesjs/blob/master/CONTRIBUTING.md 5 | 2. Use the GitHub Issues EXCLUSIVELY for BUGS, FEATURE REQUESTS or QUESTIONS. Prefix the title of the issue with its context, eg. `[Bug]: ....` 6 | 3. Do a quick SEARCH first, to see if someone else didn't open the same issue 7 | 4. DON'T ASK to create examples/code for you, read DOCS and APIs first, then you can post what you have tried (we'd like to see your code) and what you're unable to achieve 8 | 5. All relative statements/questions have to be filled/answered, otherwise, the issue might be CLOSED 9 | 10 | ## You're submitting a BUG 11 | 1. Are you using the latest release (older versions are NOT supported)? 12 | 1. If you're not sure, type `grapesjs.version` in console and press ENTER 13 | 1. Are you facing the bug with your local copy of GrapesJS or with the current demo? 14 | 1. If a local copy 15 | 1. Indicate all informations about your OS, browser and GrapesJS version. 16 | 1. Are you able to reproduce the bug from the demo? 17 | 1. What is the expected behavior? 18 | 1. What happens instead? 19 | 1. If you're able to reproduce the bug indicate all the necessary steps 20 | 1. Attach screenshots (using KAP/LICEcap), screencasts or live demo 21 | 1. JSFiddle Starter template https://jsfiddle.net/szLp8h4n 22 | 1. CodeSandbox Starter template https://codesandbox.io/s/1r0w2pk1vl 23 | 24 | ## You're submitting a FEATURE REQUEST 25 | 1. Be sure to work on the latest version, as the feature might be already there 26 | 1. Keep in mind that the feature should be considered valid to use for everyone, not only for your case 27 | -------------------------------------------------------------------------------- /grapesjs/.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 10 5 | # Label requiring a response 6 | responseRequiredLabel: more-information-needed 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because there has been no response 10 | to our request for more information from the original author. With only the 11 | information that is currently in the issue, we don't have enough information 12 | to take action. Please reach out if you have or find the answers we need so 13 | that we can investigate further. 14 | -------------------------------------------------------------------------------- /grapesjs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .settings/ 3 | .sass-cache/ 4 | .project 5 | .idea 6 | npm-debug.log* 7 | yarn-error.log 8 | yarn.lock 9 | style/.sass-cache/ 10 | 11 | img/ 12 | images/ 13 | private/ 14 | docs/ 15 | vendor/ 16 | coverage/ 17 | node_modules/ 18 | bower_components/ 19 | grapesjs-*.tgz 20 | _index.html 21 | -------------------------------------------------------------------------------- /grapesjs/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "7.6" 4 | -------------------------------------------------------------------------------- /grapesjs/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-current, Artur Arseniev 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "GrapesJS" nor the names of its contributors may be 13 | used to endorse or promote products derived from this software without 14 | specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /grapesjs/dist/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /grapesjs/dist/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /grapesjs/dist/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /grapesjs/dist/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /grapesjs/dist/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /grapesjs/dist/fonts/main-fonts.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/main-fonts.eot -------------------------------------------------------------------------------- /grapesjs/dist/fonts/main-fonts.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/main-fonts.ttf -------------------------------------------------------------------------------- /grapesjs/dist/fonts/main-fonts.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/dist/fonts/main-fonts.woff -------------------------------------------------------------------------------- /grapesjs/src/asset_manager/model/Asset.js: -------------------------------------------------------------------------------- 1 | module.exports = require('backbone').Model.extend({ 2 | idAttribute: 'src', 3 | 4 | defaults: { 5 | type: '', 6 | src: '' 7 | }, 8 | 9 | /** 10 | * Get filename of the asset 11 | * @return {string} 12 | * @private 13 | * */ 14 | getFilename() { 15 | return this.get('src') 16 | .split('/') 17 | .pop(); 18 | }, 19 | 20 | /** 21 | * Get extension of the asset 22 | * @return {string} 23 | * @private 24 | * */ 25 | getExtension() { 26 | return this.getFilename() 27 | .split('.') 28 | .pop(); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /grapesjs/src/asset_manager/model/AssetImage.js: -------------------------------------------------------------------------------- 1 | const Asset = require('./Asset'); 2 | 3 | module.exports = Asset.extend({ 4 | defaults: { 5 | ...Asset.prototype.defaults, 6 | type: 'image', 7 | unitDim: 'px', 8 | height: 0, 9 | width: 0 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /grapesjs/src/asset_manager/model/Assets.js: -------------------------------------------------------------------------------- 1 | import TypeableCollection from 'domain_abstract/model/TypeableCollection'; 2 | 3 | module.exports = require('backbone') 4 | .Collection.extend(TypeableCollection) 5 | .extend({ 6 | types: [ 7 | { 8 | id: 'image', 9 | model: require('./AssetImage'), 10 | view: require('./../view/AssetImageView'), 11 | isType(value) { 12 | if (typeof value == 'string') { 13 | return { 14 | type: 'image', 15 | src: value 16 | }; 17 | } 18 | return value; 19 | } 20 | } 21 | ] 22 | }); 23 | -------------------------------------------------------------------------------- /grapesjs/src/asset_manager/view/AssetImageView.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./AssetView').extend({ 2 | events: { 3 | 'click [data-toggle=asset-remove]': 'onRemove', 4 | click: 'onClick', 5 | dblclick: 'onDblClick' 6 | }, 7 | 8 | getPreview() { 9 | const pfx = this.pfx; 10 | const src = this.model.get('src'); 11 | return ` 12 |
13 |
14 | `; 15 | }, 16 | 17 | getInfo() { 18 | const pfx = this.pfx; 19 | const model = this.model; 20 | let name = model.get('name'); 21 | let width = model.get('width'); 22 | let height = model.get('height'); 23 | let unit = model.get('unitDim'); 24 | let dim = width && height ? `${width}x${height}${unit}` : ''; 25 | name = name || model.getFilename(); 26 | return ` 27 |
${name}
28 |
${dim}
29 | `; 30 | }, 31 | 32 | init(o) { 33 | const pfx = this.pfx; 34 | this.className += ` ${pfx}asset-image`; 35 | }, 36 | 37 | /** 38 | * Triggered when the asset is clicked 39 | * @private 40 | * */ 41 | onClick() { 42 | var onClick = this.config.onClick; 43 | var model = this.model; 44 | this.collection.trigger('deselectAll'); 45 | this.$el.addClass(this.pfx + 'highlight'); 46 | 47 | if (typeof onClick === 'function') { 48 | onClick(model); 49 | } else { 50 | this.updateTarget(this.collection.target); 51 | } 52 | }, 53 | 54 | /** 55 | * Triggered when the asset is double clicked 56 | * @private 57 | * */ 58 | onDblClick() { 59 | const em = this.em; 60 | var onDblClick = this.config.onDblClick; 61 | var model = this.model; 62 | 63 | if (typeof onDblClick === 'function') { 64 | onDblClick(model); 65 | } else { 66 | this.updateTarget(this.collection.target); 67 | em && em.get('Modal').close(); 68 | } 69 | 70 | var onSelect = this.collection.onSelect; 71 | if (typeof onSelect == 'function') { 72 | onSelect(this.model); 73 | } 74 | }, 75 | 76 | /** 77 | * Remove asset from collection 78 | * @private 79 | * */ 80 | onRemove(e) { 81 | e.stopImmediatePropagation(); 82 | this.model.collection.remove(this.model); 83 | } 84 | }); 85 | -------------------------------------------------------------------------------- /grapesjs/src/asset_manager/view/AssetView.js: -------------------------------------------------------------------------------- 1 | module.exports = Backbone.View.extend({ 2 | initialize(o = {}) { 3 | this.options = o; 4 | this.collection = o.collection; 5 | const config = o.config || {}; 6 | this.config = config; 7 | this.pfx = config.stylePrefix || ''; 8 | this.ppfx = config.pStylePrefix || ''; 9 | this.em = config.em; 10 | this.className = this.pfx + 'asset'; 11 | this.listenTo(this.model, 'destroy remove', this.remove); 12 | this.model.view = this; 13 | const init = this.init && this.init.bind(this); 14 | init && init(o); 15 | }, 16 | 17 | template() { 18 | const pfx = this.pfx; 19 | return ` 20 |
21 | ${this.getPreview()} 22 |
23 |
24 | ${this.getInfo()} 25 |
26 |
27 | ⨯ 28 |
29 | `; 30 | }, 31 | 32 | /** 33 | * Update target if exists 34 | * @param {Model} target 35 | * @private 36 | * */ 37 | updateTarget(target) { 38 | if (target && target.set) { 39 | target.set('attributes', _.clone(target.get('attributes'))); 40 | target.set('src', this.model.get('src')); 41 | } 42 | }, 43 | 44 | getPreview() { 45 | return ''; 46 | }, 47 | 48 | getInfo() { 49 | return ''; 50 | }, 51 | 52 | render() { 53 | const el = this.el; 54 | el.innerHTML = this.template(this, this.model); 55 | el.className = this.className; 56 | return this; 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Specify the element to use as a container, string (query) or HTMLElement 3 | // With the empty value, nothing will be rendered 4 | appendTo: '', 5 | 6 | blocks: [] 7 | }; 8 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/model/Block.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Category = require('./Category'); 3 | 4 | module.exports = Backbone.Model.extend({ 5 | defaults: { 6 | label: '', 7 | content: '', 8 | category: '', 9 | attributes: {} 10 | }, 11 | 12 | initialize(opts = {}) { 13 | let category = this.get('category'); 14 | 15 | if (category) { 16 | if (typeof category == 'string') { 17 | var catObj = new Category({ 18 | id: category, 19 | label: category 20 | }); 21 | } 22 | } 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/model/Blocks.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Block = require('./Block'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | model: Block 6 | }); 7 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/model/Categories.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Collection.extend({ 4 | model: require('./Category') 5 | }); 6 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/model/Category.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | id: '', 6 | label: '', 7 | open: true, 8 | attributes: {} 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /grapesjs/src/block_manager/view/CategoryView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.View.extend({ 4 | template: _.template(` 5 |
6 | 7 | <%= label %> 8 |
9 |
10 | `), 11 | 12 | events: {}, 13 | 14 | initialize(o = {}, config = {}) { 15 | this.config = config; 16 | const pfx = this.config.pStylePrefix || ''; 17 | this.pfx = pfx; 18 | this.caretR = 'fa fa-caret-right'; 19 | this.caretD = 'fa fa-caret-down'; 20 | this.iconClass = `${pfx}caret-icon`; 21 | this.activeClass = `${pfx}open`; 22 | this.className = `${pfx}block-category`; 23 | this.events[`click .${pfx}title`] = 'toggle'; 24 | this.listenTo(this.model, 'change:open', this.updateVisibility); 25 | this.delegateEvents(); 26 | }, 27 | 28 | updateVisibility() { 29 | if (this.model.get('open')) this.open(); 30 | else this.close(); 31 | }, 32 | 33 | open() { 34 | this.el.className = `${this.className} ${this.activeClass}`; 35 | this.getIconEl().className = `${this.iconClass} ${this.caretD}`; 36 | this.getBlocksEl().style.display = ''; 37 | }, 38 | 39 | close() { 40 | this.el.className = this.className; 41 | this.getIconEl().className = `${this.iconClass} ${this.caretR}`; 42 | this.getBlocksEl().style.display = 'none'; 43 | }, 44 | 45 | toggle() { 46 | var model = this.model; 47 | model.set('open', !model.get('open')); 48 | }, 49 | 50 | getIconEl() { 51 | if (!this.iconEl) { 52 | this.iconEl = this.el.querySelector('.' + this.iconClass); 53 | } 54 | 55 | return this.iconEl; 56 | }, 57 | 58 | getBlocksEl() { 59 | if (!this.blocksEl) { 60 | this.blocksEl = this.el.querySelector('.' + this.pfx + 'blocks-c'); 61 | } 62 | 63 | return this.blocksEl; 64 | }, 65 | 66 | append(el) { 67 | this.getBlocksEl().appendChild(el); 68 | }, 69 | 70 | render() { 71 | this.el.innerHTML = this.template({ 72 | pfx: this.pfx, 73 | label: this.model.get('label') 74 | }); 75 | this.el.className = this.className; 76 | this.$el.css({ order: this.model.get('order') }); 77 | this.updateVisibility(); 78 | return this; 79 | } 80 | }); 81 | -------------------------------------------------------------------------------- /grapesjs/src/canvas/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'cv-', 3 | 4 | // Coming soon 5 | rulers: false, 6 | 7 | /* 8 | * Append external scripts in head of the iframe before renderBody content 9 | * In this case, you have to add them manually later in the final HTML page 10 | * @example 11 | * scripts: [ 12 | * 'https://...', 13 | * ] 14 | */ 15 | scripts: [], 16 | 17 | /* 18 | * Append external styles. This styles won't be added to the final HTML/CSS 19 | * @example 20 | * styles: [ 21 | * 'https://...', 22 | * ] 23 | */ 24 | styles: [], 25 | 26 | /** 27 | * Add custom badge naming strategy 28 | * @example 29 | * customBadgeLabel: function(ComponentModel) { 30 | * return ComponentModel.getName(); 31 | * } 32 | */ 33 | customBadgeLabel: function(ComponentModel) { 34 | var propertyName; 35 | var property = ComponentModel.get('traits').where({ name: 'property' })[0]; 36 | if (property) { 37 | propertyName = property.get('value'); 38 | } 39 | if (propertyName && propertyName !== '') { 40 | return ComponentModel.getName() + ' - ' + propertyName; 41 | } 42 | return ComponentModel.getName(); 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /grapesjs/src/canvas/model/Canvas.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Frame = require('./Frame'); 3 | 4 | module.exports = Backbone.Model.extend({ 5 | defaults: { 6 | frame: '', 7 | wrapper: '', 8 | rulers: false 9 | }, 10 | 11 | initialize(config) { 12 | var conf = this.conf || {}; 13 | this.set('frame', new Frame(conf.frame)); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /grapesjs/src/canvas/model/Frame.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | wrapper: '', 6 | width: '', 7 | height: '', 8 | attributes: {} 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /grapesjs/src/canvas/view/FrameView.js: -------------------------------------------------------------------------------- 1 | import { bindAll } from 'underscore'; 2 | 3 | const motionsEv = 4 | 'transitionend oTransitionEnd transitionend webkitTransitionEnd'; 5 | 6 | module.exports = require('backbone').View.extend({ 7 | tagName: 'iframe', 8 | 9 | attributes: { 10 | allowfullscreen: 'allowfullscreen' 11 | }, 12 | 13 | initialize(o) { 14 | bindAll(this, 'udpateOffset'); 15 | this.config = o.config || {}; 16 | this.ppfx = this.config.pStylePrefix || ''; 17 | this.em = this.config.em; 18 | this.listenTo(this.em, 'change:device', this.updateDim); 19 | }, 20 | 21 | /** 22 | * Update dimensions of the frame 23 | * @private 24 | */ 25 | updateDim(model) { 26 | const em = this.em; 27 | const device = em.getDeviceModel(); 28 | const style = this.el.style; 29 | const currW = style.width || ''; 30 | const currH = style.height || ''; 31 | const newW = device ? device.get('width') : ''; 32 | const newH = device ? device.get('height') : ''; 33 | const noChanges = currW == newW && currH == newH; 34 | style.width = newW; 35 | style.height = newH; 36 | this.udpateOffset(); 37 | // Prevent fixed highlighting box which appears when on 38 | // component hover during the animation 39 | em.stopDefault({ preserveSelected: 1 }); 40 | noChanges ? this.udpateOffset() : this.$el.on(motionsEv, this.udpateOffset); 41 | }, 42 | 43 | udpateOffset() { 44 | const em = this.em; 45 | const offset = em.get('Canvas').getOffset(); 46 | em.set('canvasOffset', offset); 47 | em.runDefault({ preserveSelected: 1 }); 48 | this.$el.off(motionsEv, this.udpateOffset); 49 | }, 50 | 51 | getBody() { 52 | this.$el.contents().find('body'); 53 | }, 54 | 55 | getWrapper() { 56 | return this.$el.contents().find('body > div'); 57 | }, 58 | 59 | render() { 60 | this.$el.attr({ class: this.ppfx + 'frame' }); 61 | return this; 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Style prefix 3 | stylePrefix: 'cm-', 4 | 5 | inlineCss: false 6 | }; 7 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/model/CodeMirrorEditor.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var CodeMirror = require('codemirror/lib/codemirror'); 3 | var htmlMode = require('codemirror/mode/htmlmixed/htmlmixed'); 4 | var cssMode = require('codemirror/mode/css/css'); 5 | var formatting = require('codemirror-formatting'); 6 | 7 | module.exports = Backbone.Model.extend({ 8 | defaults: { 9 | input: '', 10 | label: '', 11 | codeName: '', 12 | theme: '', 13 | readOnly: true, 14 | lineNumbers: true 15 | }, 16 | 17 | /** @inheritdoc */ 18 | init(el) { 19 | this.editor = CodeMirror.fromTextArea(el, { 20 | dragDrop: false, 21 | lineWrapping: true, 22 | mode: this.get('codeName'), 23 | ...this.attributes 24 | }); 25 | 26 | return this; 27 | }, 28 | 29 | /** @inheritdoc */ 30 | setContent(v) { 31 | if (!this.editor) return; 32 | this.editor.setValue(v); 33 | if (this.editor.autoFormatRange) { 34 | CodeMirror.commands.selectAll(this.editor); 35 | this.editor.autoFormatRange( 36 | this.editor.getCursor(true), 37 | this.editor.getCursor(false) 38 | ); 39 | CodeMirror.commands.goDocStart(this.editor); 40 | } 41 | } 42 | }); 43 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/model/HtmlGenerator.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | build(model, opts = {}) { 5 | const models = model.get('components'); 6 | 7 | if (opts.exportWrapper) { 8 | return opts.wrappesIsBody 9 | ? `${this.buildModels(models)}` 10 | : model.toHTML(); 11 | } 12 | 13 | return this.buildModels(models); 14 | }, 15 | 16 | buildModels(models) { 17 | let code = ''; 18 | models.each(model => { 19 | code += model.toHTML(); 20 | }); 21 | return code; 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/model/JsGenerator.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | mapModel(model) { 5 | var code = ''; 6 | var script = model.get('script'); 7 | var type = model.get('type'); 8 | var comps = model.get('components'); 9 | var id = model.getId(); 10 | 11 | if (script) { 12 | // If the component has scripts we need to expose his ID 13 | var attr = model.get('attributes'); 14 | attr = _.extend({}, attr, { id }); 15 | model.set('attributes', attr); 16 | var scrStr = model.getScriptString(); 17 | 18 | // If the script was updated, I'll put its code in a separate container 19 | if (model.get('scriptUpdated')) { 20 | this.mapJs[type + '-' + id] = { ids: [id], code: scrStr }; 21 | } else { 22 | var mapType = this.mapJs[type]; 23 | 24 | if (mapType) { 25 | mapType.ids.push(id); 26 | } else { 27 | this.mapJs[type] = { ids: [id], code: scrStr }; 28 | } 29 | } 30 | } 31 | 32 | comps.each(function(model) { 33 | code += this.mapModel(model); 34 | }, this); 35 | 36 | return code; 37 | }, 38 | 39 | build(model) { 40 | this.mapJs = {}; 41 | this.mapModel(model); 42 | 43 | var code = ''; 44 | 45 | for (var type in this.mapJs) { 46 | var mapType = this.mapJs[type]; 47 | var ids = '#' + mapType.ids.join(', #'); 48 | code += ` 49 | var items = document.querySelectorAll('${ids}'); 50 | for (var i = 0, len = items.length; i < len; i++) { 51 | (function(){${mapType.code}}.bind(items[i]))(); 52 | }`; 53 | } 54 | 55 | return code; 56 | } 57 | }); 58 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/model/JsonGenerator.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | /** @inheritdoc */ 5 | build(model) { 6 | var json = model.toJSON(); 7 | this.beforeEach(json); 8 | 9 | _.each( 10 | json, 11 | function(v, attr) { 12 | var obj = json[attr]; 13 | if (obj instanceof Backbone.Model) { 14 | json[attr] = this.build(obj); 15 | } else if (obj instanceof Backbone.Collection) { 16 | var coll = obj; 17 | json[attr] = []; 18 | if (coll.length) { 19 | coll.each(function(el, index) { 20 | json[attr][index] = this.build(el); 21 | }, this); 22 | } 23 | } 24 | }, 25 | this 26 | ); 27 | 28 | return json; 29 | }, 30 | 31 | /** 32 | * Execute on each object 33 | * @param {Object} obj 34 | */ 35 | beforeEach(obj) { 36 | delete obj.status; 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /grapesjs/src/code_manager/view/EditorView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.View.extend({ 4 | template: _.template(` 5 |
6 |
<%= label %>
7 |
8 |
`), 9 | 10 | initialize(o) { 11 | this.config = o.config || {}; 12 | this.pfx = this.config.stylePrefix; 13 | }, 14 | 15 | render() { 16 | var obj = this.model.toJSON(); 17 | obj.pfx = this.pfx; 18 | this.$el.html(this.template(obj)); 19 | this.$el.attr('class', this.pfx + 'editor-c'); 20 | this.$el.find('#' + this.pfx + 'code').append(this.model.get('input')); 21 | return this; 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /grapesjs/src/commands/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ESCAPE_KEY: 27, 3 | 4 | stylePrefix: 'com-', 5 | 6 | defaults: [], 7 | 8 | // Editor model 9 | em: null, 10 | 11 | // If true center new first-level components 12 | firstCentered: true, 13 | 14 | // If true the new component will created with 'height', else 'min-height' 15 | newFixedH: false, 16 | 17 | // Minimum height (in px) of new component 18 | minComponentH: 50, 19 | 20 | // Minimum width (in px) of component on creation 21 | minComponentW: 50 22 | }; 23 | -------------------------------------------------------------------------------- /grapesjs/src/commands/model/Command.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | id: '' 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /grapesjs/src/commands/model/Commands.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Command = require('./Command'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | model: Command 6 | }); 7 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/DeleteComponent.js: -------------------------------------------------------------------------------- 1 | const SelectComponent = require('./SelectComponent'); 2 | const $ = Backbone.$; 3 | 4 | module.exports = _.extend({}, SelectComponent, { 5 | init(o) { 6 | _.bindAll(this, 'startDelete', 'stopDelete', 'onDelete'); 7 | this.hoverClass = this.pfx + 'hover-delete'; 8 | this.badgeClass = this.pfx + 'badge-red'; 9 | }, 10 | 11 | enable() { 12 | var that = this; 13 | this.$el 14 | .find('*') 15 | .mouseover(this.startDelete) 16 | .mouseout(this.stopDelete) 17 | .click(this.onDelete); 18 | }, 19 | 20 | /** 21 | * Start command 22 | * @param {Object} e 23 | * @private 24 | */ 25 | startDelete(e) { 26 | e.stopPropagation(); 27 | var $this = $(e.target); 28 | 29 | // Show badge if possible 30 | if ($this.data('model').get('removable')) { 31 | $this.addClass(this.hoverClass); 32 | this.attachBadge($this.get(0)); 33 | } 34 | }, 35 | 36 | /** 37 | * Stop command 38 | * @param {Object} e 39 | * @private 40 | */ 41 | stopDelete(e) { 42 | e.stopPropagation(); 43 | var $this = $(e.target); 44 | $this.removeClass(this.hoverClass); 45 | 46 | // Hide badge if possible 47 | if (this.badge) this.badge.css({ left: -1000, top: -1000 }); 48 | }, 49 | 50 | /** 51 | * Delete command 52 | * @param {Object} e 53 | * @private 54 | */ 55 | onDelete(e) { 56 | e.stopPropagation(); 57 | var $this = $(e.target); 58 | 59 | // Do nothing in case can't remove 60 | if (!$this.data('model').get('removable')) return; 61 | 62 | $this.data('model').destroy(); 63 | this.removeBadge(); 64 | this.clean(); 65 | }, 66 | 67 | /** 68 | * Updates badge label 69 | * @param {Object} model 70 | * @private 71 | * */ 72 | updateBadgeLabel(model) { 73 | this.badge.html('Remove ' + model.getName()); 74 | } 75 | }); 76 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/Drag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(editor, sender, opts) { 3 | var el = (opts && opts.el) || ''; 4 | var canvas = editor.Canvas; 5 | var dragger = this.dragger; 6 | var options = opts.options || {}; 7 | var canvasView = canvas.getCanvasView(); 8 | options.prefix = editor.getConfig().stylePrefix; 9 | options.mousePosFetcher = canvas.getMouseRelativePos; 10 | options.posFetcher = canvasView.getElementPos.bind(canvasView); 11 | 12 | // Create the resizer for the canvas if not yet created 13 | if (!dragger) { 14 | dragger = editor.Utils.Dragger.init(options); 15 | this.dragger = dragger; 16 | } 17 | 18 | dragger.setOptions(options); 19 | dragger.focus(el); 20 | 21 | if (options.event) { 22 | dragger.start(options.event); 23 | } 24 | 25 | return dragger; 26 | }, 27 | 28 | stop() { 29 | if (this.canvasResizer) this.canvasResizer.blur(); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/ExportTemplate.js: -------------------------------------------------------------------------------- 1 | const $ = Backbone.$; 2 | 3 | module.exports = { 4 | run(editor, sender, opts = {}) { 5 | sender && sender.set && sender.set('active', 0); 6 | const config = editor.getConfig(); 7 | const modal = editor.Modal; 8 | const pfx = config.stylePrefix; 9 | this.cm = editor.CodeManager || null; 10 | 11 | if (!this.$editors) { 12 | const oHtmlEd = this.buildEditor('htmlmixed', 'hopscotch', 'HTML'); 13 | const oCsslEd = this.buildEditor('css', 'hopscotch', 'CSS'); 14 | this.htmlEditor = oHtmlEd.el; 15 | this.cssEditor = oCsslEd.el; 16 | const $editors = $(`
`); 17 | $editors.append(oHtmlEd.$el).append(oCsslEd.$el); 18 | this.$editors = $editors; 19 | } 20 | 21 | modal.setTitle(config.textViewCode); 22 | modal.setContent(this.$editors); 23 | modal.open(); 24 | this.htmlEditor.setContent(editor.getHtml()); 25 | this.cssEditor.setContent(editor.getCss()); 26 | }, 27 | 28 | stop(editor) { 29 | const modal = editor.Modal; 30 | modal && modal.close(); 31 | }, 32 | 33 | buildEditor(codeName, theme, label) { 34 | const input = document.createElement('textarea'); 35 | !this.codeMirror && (this.codeMirror = this.cm.getViewer('CodeMirror')); 36 | 37 | const el = this.codeMirror.clone().set({ 38 | label, 39 | codeName, 40 | theme, 41 | input 42 | }); 43 | 44 | const $el = new this.cm.EditorView({ 45 | model: el, 46 | config: this.cm.getConfig() 47 | }).render().$el; 48 | 49 | el.init(input); 50 | 51 | return { el, $el }; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/Fullscreen.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * Check if fullscreen mode is enabled 4 | * @return {Boolean} 5 | */ 6 | isEnabled() { 7 | var d = document; 8 | if ( 9 | d.fullscreenElement || 10 | d.webkitFullscreenElement || 11 | d.mozFullScreenElement 12 | ) 13 | return 1; 14 | else return 0; 15 | }, 16 | 17 | /** 18 | * Enable fullscreen mode and return browser prefix 19 | * @param {HTMLElement} el 20 | * @return {string} 21 | */ 22 | enable(el) { 23 | var pfx = ''; 24 | if (el.requestFullscreen) el.requestFullscreen(); 25 | else if (el.webkitRequestFullscreen) { 26 | pfx = 'webkit'; 27 | el.webkitRequestFullscreen(); 28 | } else if (el.mozRequestFullScreen) { 29 | pfx = 'moz'; 30 | el.mozRequestFullScreen(); 31 | } else if (el.msRequestFullscreen) el.msRequestFullscreen(); 32 | else console.warn('Fullscreen not supported'); 33 | return pfx; 34 | }, 35 | 36 | /** 37 | * Disable fullscreen mode 38 | */ 39 | disable() { 40 | var d = document; 41 | if (d.exitFullscreen) d.exitFullscreen(); 42 | else if (d.webkitExitFullscreen) d.webkitExitFullscreen(); 43 | else if (d.mozCancelFullScreen) d.mozCancelFullScreen(); 44 | else if (d.msExitFullscreen) d.msExitFullscreen(); 45 | }, 46 | 47 | /** 48 | * Triggered when the state of the fullscreen is changed. Inside detects if 49 | * it's enabled 50 | * @param {strinf} pfx Browser prefix 51 | * @param {Event} e 52 | */ 53 | fsChanged(pfx, e) { 54 | var d = document; 55 | var ev = (pfx || '') + 'fullscreenchange'; 56 | if (!this.isEnabled()) { 57 | this.stop(null, this.sender); 58 | document.removeEventListener(ev, this.fsChanged); 59 | } 60 | }, 61 | 62 | run(editor, sender) { 63 | this.sender = sender; 64 | var pfx = this.enable(editor.getContainer()); 65 | this.fsChanged = this.fsChanged.bind(this, pfx); 66 | document.addEventListener(pfx + 'fullscreenchange', this.fsChanged); 67 | if (editor) editor.trigger('change:canvasOffset'); 68 | }, 69 | 70 | stop(editor, sender) { 71 | if (sender && sender.set) sender.set('active', false); 72 | this.disable(); 73 | if (editor) editor.trigger('change:canvasOffset'); 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/ImageComponent.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var InsertCustom = require('./InsertCustom'); 3 | 4 | module.exports = _.extend({}, InsertCustom, { 5 | /** 6 | * Trigger before insert 7 | * @param {Object} object 8 | * @private 9 | * 10 | * */ 11 | beforeInsert(object) { 12 | object.type = 'image'; 13 | object.style = {}; 14 | object.attributes = {}; 15 | object.attributes.onmousedown = 'return false'; 16 | if ( 17 | this.config.firstCentered && 18 | this.getCanvasWrapper() == this.sorter.target 19 | ) { 20 | object.style.margin = '0 auto'; 21 | } 22 | }, 23 | 24 | /** 25 | * Trigger after insert 26 | * @param {Object} model Model created after insert 27 | * @private 28 | * */ 29 | afterInsert(model) { 30 | model.trigger('dblclick'); 31 | if (this.sender) this.sender.set('active', false); 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/InsertCustom.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var CreateComponent = require('./CreateComponent'); 3 | 4 | module.exports = _.extend({}, CreateComponent, { 5 | init(...args) { 6 | CreateComponent.init.apply(this, args); 7 | _.bindAll(this, 'insertComponent'); 8 | this.allowDraw = 0; 9 | }, 10 | 11 | /** 12 | * Run method 13 | * @private 14 | * */ 15 | run(em, sender, options) { 16 | this.em = em; 17 | this.sender = sender; 18 | this.opt = options || {}; 19 | this.$wr = this.$wrapper; 20 | this.enable(); 21 | }, 22 | 23 | enable(...args) { 24 | CreateComponent.enable.apply(this, args); 25 | this.$wr.on('click', this.insertComponent); 26 | }, 27 | 28 | /** 29 | * Start insert event 30 | * @private 31 | * */ 32 | insertComponent() { 33 | this.$wr.off('click', this.insertComponent); 34 | this.stopSelectPosition(); 35 | var object = this.buildContent(); 36 | this.beforeInsert(object); 37 | var index = this.sorter.lastPos.index; 38 | // By default, collections do not trigger add event, so silent is used 39 | var model = this.create(this.sorter.target, object, index, null, { 40 | silent: false 41 | }); 42 | 43 | if (this.opt.terminateAfterInsert && this.sender) 44 | this.sender.set('active', false); 45 | else this.enable(); 46 | 47 | if (!model) return; 48 | 49 | this.afterInsert(model, this); 50 | }, 51 | 52 | /** 53 | * Trigger before insert 54 | * @param {Object} obj 55 | * @private 56 | * */ 57 | beforeInsert(obj) {}, 58 | 59 | /** 60 | * Trigger after insert 61 | * @param {Object} model Model created after insert 62 | * @private 63 | * */ 64 | afterInsert(model) {}, 65 | 66 | /** 67 | * Create different object, based on content, to insert inside canvas 68 | * 69 | * @return {Object} 70 | * @private 71 | * */ 72 | buildContent() { 73 | return this.opt.content || {}; 74 | } 75 | }); 76 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/OpenAssets.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(editor, sender, opts = {}) { 3 | const modal = editor.Modal; 4 | const am = editor.AssetManager; 5 | const config = am.getConfig(); 6 | const amContainer = am.getContainer(); 7 | const title = opts.modalTitle || config.modalTitle || ''; 8 | const types = opts.types; 9 | const accept = opts.accept; 10 | 11 | am.setTarget(opts.target); 12 | am.onClick(opts.onClick); 13 | am.onDblClick(opts.onDblClick); 14 | am.onSelect(opts.onSelect); 15 | 16 | if (!this.rendered || types) { 17 | let assets = am.getAll(); 18 | 19 | if (types) { 20 | assets = assets.filter(a => types.indexOf(a.get('type')) !== -1); 21 | } 22 | 23 | am.render(assets); 24 | this.rendered = 1; 25 | } 26 | 27 | if (accept) { 28 | const uploadEl = amContainer.querySelector( 29 | `input#${config.stylePrefix}uploadFile` 30 | ); 31 | uploadEl && uploadEl.setAttribute('accept', accept); 32 | } 33 | 34 | modal.setTitle(title); 35 | modal.setContent(amContainer); 36 | modal.open(); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/OpenBlocks.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(editor, sender) { 3 | const bm = editor.BlockManager; 4 | const pn = editor.Panels; 5 | 6 | if (!this.blocks) { 7 | bm.render(); 8 | const id = 'views-container'; 9 | const blocks = document.createElement('div'); 10 | const panels = pn.getPanel(id) || pn.addPanel({ id }); 11 | blocks.appendChild(bm.getContainer()); 12 | panels.set('appendContent', blocks).trigger('change:appendContent'); 13 | this.blocks = blocks; 14 | } 15 | 16 | this.blocks.style.display = 'block'; 17 | }, 18 | 19 | stop() { 20 | const blocks = this.blocks; 21 | blocks && (blocks.style.display = 'none'); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/OpenLayers.js: -------------------------------------------------------------------------------- 1 | const Layers = require('navigator'); 2 | const $ = Backbone.$; 3 | 4 | module.exports = { 5 | run(editor) { 6 | const lm = editor.LayerManager; 7 | const pn = editor.Panels; 8 | 9 | if (!this.layers) { 10 | const id = 'views-container'; 11 | const layers = document.createElement('div'); 12 | const panels = pn.getPanel(id) || pn.addPanel({ id }); 13 | layers.appendChild(lm.render()); 14 | panels.set('appendContent', layers).trigger('change:appendContent'); 15 | this.layers = layers; 16 | } 17 | 18 | this.layers.style.display = 'block'; 19 | }, 20 | 21 | stop() { 22 | const layers = this.layers; 23 | layers && (layers.style.display = 'none'); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/OpenStyleManager.js: -------------------------------------------------------------------------------- 1 | const StyleManager = require('style_manager'); 2 | const Backbone = require('backbone'); 3 | const $ = Backbone.$; 4 | 5 | module.exports = { 6 | run(em, sender) { 7 | this.sender = sender; 8 | if (!this.$cn) { 9 | var config = em.getConfig(), 10 | panels = em.Panels; 11 | // Main container 12 | this.$cn = $('
'); 13 | // Secondary container 14 | this.$cn2 = $('
'); 15 | this.$cn.append(this.$cn2); 16 | 17 | // Device Manager 18 | var dvm = em.DeviceManager; 19 | if (dvm && config.showDevices) { 20 | var devicePanel = panels.addPanel({ id: 'devices-c' }); 21 | devicePanel 22 | .set('appendContent', dvm.render()) 23 | .trigger('change:appendContent'); 24 | } 25 | 26 | // Class Manager container 27 | var clm = em.SelectorManager; 28 | if (clm) this.$cn2.append(clm.render([])); 29 | 30 | this.$cn2.append(em.StyleManager.render()); 31 | var smConfig = em.StyleManager.getConfig(); 32 | const pfx = smConfig.stylePrefix; 33 | // Create header 34 | this.$header = $( 35 | `
${smConfig.textNoElement}
` 36 | ); 37 | this.$cn.append(this.$header); 38 | 39 | // Create panel if not exists 40 | if (!panels.getPanel('views-container')) 41 | this.panel = panels.addPanel({ id: 'views-container' }); 42 | else this.panel = panels.getPanel('views-container'); 43 | 44 | // Add all containers to the panel 45 | this.panel.set('appendContent', this.$cn).trigger('change:appendContent'); 46 | 47 | this.target = em.editor; 48 | this.listenTo(this.target, 'change:selectedComponent', this.toggleSm); 49 | } 50 | this.toggleSm(); 51 | }, 52 | 53 | /** 54 | * Toggle Style Manager visibility 55 | * @private 56 | */ 57 | toggleSm() { 58 | const sender = this.sender; 59 | if (sender && sender.get && !sender.get('active')) return; 60 | 61 | if (this.target.get('selectedComponent')) { 62 | this.$cn2.show(); 63 | this.$header.hide(); 64 | } else { 65 | this.$cn2.hide(); 66 | this.$header.show(); 67 | } 68 | }, 69 | 70 | stop() { 71 | // Hide secondary container if exists 72 | if (this.$cn2) this.$cn2.hide(); 73 | 74 | // Hide header container if exists 75 | if (this.$header) this.$header.hide(); 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/OpenTraitManager.js: -------------------------------------------------------------------------------- 1 | const $ = require('backbone').$; 2 | 3 | module.exports = { 4 | run(editor, sender) { 5 | this.sender = sender; 6 | 7 | var config = editor.Config; 8 | var pfx = config.stylePrefix; 9 | var tm = editor.TraitManager; 10 | var panelC; 11 | 12 | if (!this.$cn) { 13 | var tmView = tm.getTraitsViewer(); 14 | var confTm = tm.getConfig(); 15 | this.$cn = $('
'); 16 | this.$cn2 = $('
'); 17 | this.$cn.append(this.$cn2); 18 | this.$header = $('
').append( 19 | `
${confTm.textNoElement}
` 20 | ); 21 | this.$cn.append(this.$header); 22 | this.$cn2.append( 23 | `
${confTm.labelContainer}
` 24 | ); 25 | this.$cn2.append(tmView.render().el); 26 | var panels = editor.Panels; 27 | 28 | if (!panels.getPanel('views-container')) 29 | panelC = panels.addPanel({ id: 'views-container' }); 30 | else panelC = panels.getPanel('views-container'); 31 | 32 | panelC 33 | .set('appendContent', this.$cn.get(0)) 34 | .trigger('change:appendContent'); 35 | 36 | this.target = editor.getModel(); 37 | this.listenTo(this.target, 'change:selectedComponent', this.toggleTm); 38 | } 39 | 40 | this.toggleTm(); 41 | }, 42 | 43 | /** 44 | * Toggle Trait Manager visibility 45 | * @private 46 | */ 47 | toggleTm() { 48 | const sender = this.sender; 49 | if (sender && sender.get && !sender.get('active')) return; 50 | 51 | if (this.target.get('selectedComponent')) { 52 | this.$cn2.show(); 53 | this.$header.hide(); 54 | } else { 55 | this.$cn2.hide(); 56 | this.$header.show(); 57 | } 58 | }, 59 | 60 | stop() { 61 | this.$cn2 && this.$cn2.hide(); 62 | this.$header && this.$header.hide(); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/Preview.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | getPanels(editor) { 3 | if (!this.panels) this.panels = editor.Panels.getPanelsEl(); 4 | return this.panels; 5 | }, 6 | 7 | tglPointers(editor, v) { 8 | var elP = editor.Canvas.getBody().querySelectorAll( 9 | '.' + this.ppfx + 'no-pointer' 10 | ); 11 | _.each(elP, item => { 12 | item.style.pointerEvents = v ? '' : 'all'; 13 | }); 14 | }, 15 | 16 | run(editor, sender) { 17 | if (sender && sender.set) sender.set('active', false); 18 | editor.stopCommand('sw-visibility'); 19 | editor.getModel().stopDefault(); 20 | var that = this; 21 | var panels = this.getPanels(editor); 22 | var canvas = editor.Canvas.getElement(); 23 | var editorEl = editor.getEl(); 24 | var pfx = editor.Config.stylePrefix; 25 | if (!this.helper) { 26 | this.helper = document.createElement('span'); 27 | this.helper.className = pfx + 'off-prv fa fa-eye-slash'; 28 | editorEl.appendChild(this.helper); 29 | this.helper.onclick = () => { 30 | editor.stopCommand('preview'); 31 | }; 32 | } 33 | this.helper.style.display = 'inline-block'; 34 | this.tglPointers(editor); 35 | 36 | /* 37 | editor.Canvas.getBody().querySelectorAll('.' + pfx + 'no-pointer').forEach(function(){ 38 | this.style.pointerEvents = 'all'; 39 | });*/ 40 | 41 | panels.style.display = 'none'; 42 | var canvasS = canvas.style; 43 | canvasS.width = '100%'; 44 | canvasS.height = '100%'; 45 | canvasS.top = '0'; 46 | canvasS.left = '0'; 47 | canvasS.padding = '0'; 48 | canvasS.margin = '0'; 49 | editor.trigger('change:canvasOffset'); 50 | }, 51 | 52 | stop(editor, sender) { 53 | var panels = this.getPanels(editor); 54 | editor.runCommand('sw-visibility'); 55 | editor.getModel().runDefault(); 56 | panels.style.display = 'block'; 57 | var canvas = editor.Canvas.getElement(); 58 | canvas.setAttribute('style', ''); 59 | if (this.helper) { 60 | this.helper.style.display = 'none'; 61 | } 62 | editor.trigger('change:canvasOffset'); 63 | this.tglPointers(editor, 1); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/Resize.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(editor, sender, opts) { 3 | var opt = opts || {}; 4 | var el = opt.el || ''; 5 | var canvas = editor.Canvas; 6 | var canvasResizer = this.canvasResizer; 7 | var options = opt.options || {}; 8 | var canvasView = canvas.getCanvasView(); 9 | options.ratioDefault = 1; 10 | options.appendTo = canvas.getResizerEl(); 11 | options.prefix = editor.getConfig().stylePrefix; 12 | options.posFetcher = canvasView.getElementPos.bind(canvasView); 13 | options.mousePosFetcher = canvas.getMouseRelativePos; 14 | 15 | // Create the resizer for the canvas if not yet created 16 | if (!canvasResizer || opt.forceNew) { 17 | this.canvasResizer = editor.Utils.Resizer.init(options); 18 | canvasResizer = this.canvasResizer; 19 | } 20 | 21 | canvasResizer.setOptions(options); 22 | canvasResizer.blur(); 23 | canvasResizer.focus(el); 24 | return canvasResizer; 25 | }, 26 | 27 | stop() { 28 | const resizer = this.canvasResizer; 29 | resizer && resizer.blur(); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/SelectParent.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(editor) { 3 | const sel = editor.getSelected(); 4 | let comp = sel && sel.parent(); 5 | 6 | // Recurse through the parent() chain until a selectable parent is found 7 | while (comp && !comp.get('selectable')) { 8 | comp = comp.parent(); 9 | } 10 | 11 | comp && editor.select(comp); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/SwitchVisibility.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run(ed) { 3 | ed.Canvas.getBody().className = this.ppfx + 'dashed'; 4 | }, 5 | 6 | stop(ed) { 7 | ed.Canvas.getBody().className = ''; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /grapesjs/src/commands/view/TextComponent.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var CreateComponent = require('./CreateComponent'); 3 | 4 | module.exports = _.extend({}, CreateComponent, { 5 | /** 6 | * This event is triggered at the beginning of a draw operation 7 | * @param {Object} component Object component before creation 8 | * @private 9 | * */ 10 | beforeDraw(component) { 11 | component.type = 'text'; 12 | if (!component.style) component.style = {}; 13 | component.style.padding = '10px'; 14 | }, 15 | 16 | /** 17 | * This event is triggered at the end of a draw operation 18 | * @param {Object} model Component model created 19 | * @private 20 | * */ 21 | afterDraw(model) { 22 | if (!model || !model.set) return; 23 | model.trigger('focus'); 24 | if (this.sender) this.sender.set('active', false); 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /grapesjs/src/css_composer/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Style prefix 3 | stylePrefix: 'css-', 4 | 5 | // Custom CSS string to render on top 6 | staticRules: '', 7 | 8 | // Default CSS style 9 | rules: [] 10 | }; 11 | -------------------------------------------------------------------------------- /grapesjs/src/css_composer/model/CssRules.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var CssRule = require('./CssRule'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | initialize(models, opt) { 6 | // Inject editor 7 | if (opt && opt.em) this.editor = opt.em; 8 | 9 | // Not used 10 | this.model = (attrs, options) => { 11 | var model; 12 | 13 | if (!options.em && opt && opt.em) options.em = opt.em; 14 | 15 | switch (1) { 16 | default: 17 | model = new CssRule(attrs, options); 18 | } 19 | 20 | return model; 21 | }; 22 | }, 23 | 24 | add(models, opt = {}) { 25 | if (typeof models === 'string') { 26 | models = this.editor.get('Parser').parseCss(models); 27 | } 28 | opt.em = this.editor; 29 | return Backbone.Collection.prototype.add.apply(this, [models, opt]); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /grapesjs/src/css_composer/view/CssGroupRuleView.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./CssRuleView').extend({ 2 | _createElement: function(tagName) { 3 | return document.createTextNode(''); 4 | }, 5 | 6 | render() { 7 | const model = this.model; 8 | const important = model.get('important'); 9 | this.el.textContent = model.getDeclaration({ important }); 10 | return this; 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /grapesjs/src/css_composer/view/CssRuleView.js: -------------------------------------------------------------------------------- 1 | module.exports = require('backbone').View.extend({ 2 | tagName: 'style', 3 | 4 | initialize(o = {}) { 5 | this.config = o.config || {}; 6 | const model = this.model; 7 | const toTrack = 'change:style change:state change:mediaText'; 8 | this.listenTo(model, toTrack, this.render); 9 | this.listenTo(model, 'destroy remove', this.remove); 10 | this.listenTo(model.get('selectors'), 'change', this.render); 11 | }, 12 | 13 | render() { 14 | const model = this.model; 15 | const important = model.get('important'); 16 | this.el.innerHTML = this.model.toCSS({ important }); 17 | return this; 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /grapesjs/src/device_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devices: [], 3 | 4 | deviceLabel: 'Device' 5 | }; 6 | -------------------------------------------------------------------------------- /grapesjs/src/device_manager/model/Device.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | idAttribute: 'name', 5 | 6 | defaults: { 7 | name: '', 8 | 9 | // Width to set for the editor iframe 10 | width: '', 11 | 12 | // Height to set for the editor iframe 13 | height: '', 14 | 15 | // The width which will be used in media queries, 16 | // If empty the width will be used 17 | widthMedia: null 18 | }, 19 | 20 | initialize() { 21 | if (this.get('widthMedia') == null) { 22 | this.set('widthMedia', this.get('width')); 23 | } 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /grapesjs/src/device_manager/model/Devices.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Device = require('./Device'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | model: Device 6 | }); 7 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'comp-', 3 | 4 | wrapperId: 'wrapper', 5 | 6 | wrapperName: 'Body', 7 | 8 | // Default wrapper configuration 9 | wrapper: { 10 | removable: false, 11 | copyable: false, 12 | draggable: false, 13 | components: [], 14 | traits: [], 15 | stylable: [ 16 | 'background', 17 | 'background-color', 18 | 'background-image', 19 | 'background-repeat', 20 | 'background-attachment', 21 | 'background-position', 22 | 'background-size' 23 | ] 24 | }, 25 | 26 | // Could be used for default components 27 | components: [], 28 | 29 | // Class for new image component 30 | imageCompClass: 'fa fa-picture-o', 31 | 32 | // Open assets manager on create of image component 33 | oAssetsOnCreate: true, 34 | 35 | // TODO to remove 36 | // Editor should also store the wrapper informations, but as this change might 37 | // break stuff I set ii as an opt-in option, for now. 38 | storeWrapper: 0, 39 | 40 | // List of void elements 41 | voidElements: [ 42 | 'area', 43 | 'base', 44 | 'br', 45 | 'col', 46 | 'embed', 47 | 'hr', 48 | 'img', 49 | 'input', 50 | 'keygen', 51 | 'link', 52 | 'menuitem', 53 | 'meta', 54 | 'param', 55 | 'source', 56 | 'track', 57 | 'wbr' 58 | ] 59 | }; 60 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentLink.js: -------------------------------------------------------------------------------- 1 | const Component = require('./ComponentText'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | type: 'link', 8 | tagName: 'a', 9 | traits: ['title', 'href', 'target'] 10 | }, 11 | 12 | /** 13 | * Returns object of attributes for HTML 14 | * @return {Object} 15 | * @private 16 | */ 17 | getAttrToHTML(...args) { 18 | const attr = Component.prototype.getAttrToHTML.apply(this, args); 19 | delete attr.onmousedown; 20 | return attr; 21 | } 22 | }, 23 | { 24 | isComponent(el) { 25 | let result; 26 | let avoidEdit; 27 | 28 | if (el.tagName == 'A') { 29 | result = { 30 | type: 'link', 31 | editable: 0 32 | }; 33 | 34 | // The link is editable only if, at least, one of its 35 | // children is a text node (not empty one) 36 | const children = el.childNodes; 37 | const len = children.length; 38 | if (!len) delete result.editable; 39 | 40 | for (let i = 0; i < len; i++) { 41 | const child = children[i]; 42 | 43 | if (child.nodeType == 3 && child.textContent.trim() != '') { 44 | delete result.editable; 45 | break; 46 | } 47 | } 48 | } 49 | 50 | return result; 51 | } 52 | } 53 | ); 54 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentScript.js: -------------------------------------------------------------------------------- 1 | var Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: _.extend({}, Component.prototype.defaults, { 6 | type: 'script', 7 | droppable: false, 8 | draggable: false, 9 | layerable: false 10 | }) 11 | }, 12 | { 13 | isComponent(el) { 14 | if (el.tagName == 'SCRIPT') { 15 | var result = { type: 'script' }; 16 | 17 | if (el.src) { 18 | result.src = el.src; 19 | result.onload = el.onload; 20 | } 21 | 22 | return result; 23 | } 24 | } 25 | } 26 | ); 27 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentSvg.js: -------------------------------------------------------------------------------- 1 | var Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | highlightable: 0 8 | }, 9 | 10 | getName() { 11 | let name = this.get('tagName'); 12 | let customName = this.get('custom-name'); 13 | name = name.charAt(0).toUpperCase() + name.slice(1); 14 | return customName || name; 15 | } 16 | }, 17 | { 18 | isComponent(el) { 19 | if (SVGElement && el instanceof SVGElement) { 20 | // Some SVG elements require uppercase letters (eg. ) 21 | const tagName = el.tagName; 22 | // Make the root resizable 23 | const resizable = tagName == 'svg' ? true : false; 24 | 25 | return { 26 | tagName, 27 | type: 'svg', 28 | resizable 29 | }; 30 | } 31 | } 32 | } 33 | ); 34 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTable.js: -------------------------------------------------------------------------------- 1 | const Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | type: 'table', 8 | tagName: 'table', 9 | droppable: ['tbody', 'thead', 'tfoot'] 10 | }, 11 | 12 | initialize(o, opt) { 13 | Component.prototype.initialize.apply(this, arguments); 14 | const components = this.get('components'); 15 | !components.length && components.add({ type: 'tbody' }); 16 | } 17 | }, 18 | { 19 | isComponent(el) { 20 | let result = ''; 21 | 22 | if (el.tagName == 'TABLE') { 23 | result = { type: 'table' }; 24 | } 25 | 26 | return result; 27 | } 28 | } 29 | ); 30 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTableBody.js: -------------------------------------------------------------------------------- 1 | const Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | type: 'tbody', 8 | tagName: 'tbody', 9 | draggable: ['table'], 10 | droppable: ['tr'], 11 | columns: 1, 12 | rows: 1 13 | }, 14 | 15 | initialize(o, opt) { 16 | Component.prototype.initialize.apply(this, arguments); 17 | const components = this.get('components'); 18 | let columns = this.get('columns'); 19 | let rows = this.get('rows'); 20 | 21 | // Init components if empty 22 | if (!components.length) { 23 | const rowsToAdd = []; 24 | 25 | while (rows--) { 26 | const columnsToAdd = []; 27 | let clm = columns; 28 | 29 | while (clm--) { 30 | columnsToAdd.push({ 31 | type: 'cell', 32 | classes: ['cell'] 33 | }); 34 | } 35 | 36 | rowsToAdd.push({ 37 | type: 'row', 38 | classes: ['row'], 39 | components: columnsToAdd 40 | }); 41 | } 42 | 43 | components.add(rowsToAdd); 44 | } 45 | } 46 | }, 47 | { 48 | isComponent(el) { 49 | let result = ''; 50 | 51 | if (el.tagName == 'TBODY') { 52 | result = { type: 'tbody' }; 53 | } 54 | 55 | return result; 56 | } 57 | } 58 | ); 59 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTableCell.js: -------------------------------------------------------------------------------- 1 | const Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | type: 'cell', 8 | tagName: 'td', 9 | draggable: ['tr'] 10 | } 11 | }, 12 | { 13 | isComponent(el) { 14 | let result = ''; 15 | const tag = el.tagName; 16 | 17 | if (tag == 'TD' || tag == 'TH') { 18 | result = { 19 | type: 'cell', 20 | tagName: tag.toLowerCase() 21 | }; 22 | } 23 | 24 | return result; 25 | } 26 | } 27 | ); 28 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTableFoot.js: -------------------------------------------------------------------------------- 1 | const ComponentTableBody = require('./ComponentTableBody'); 2 | 3 | module.exports = ComponentTableBody.extend( 4 | { 5 | defaults: { 6 | ...ComponentTableBody.prototype.defaults, 7 | type: 'tfoot', 8 | tagName: 'tfoot' 9 | } 10 | }, 11 | { 12 | isComponent(el) { 13 | let result = ''; 14 | 15 | if (el.tagName == 'TFOOT') { 16 | result = { type: 'tfoot' }; 17 | } 18 | 19 | return result; 20 | } 21 | } 22 | ); 23 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTableHead.js: -------------------------------------------------------------------------------- 1 | const ComponentTableBody = require('./ComponentTableBody'); 2 | 3 | module.exports = ComponentTableBody.extend( 4 | { 5 | defaults: { 6 | ...ComponentTableBody.prototype.defaults, 7 | type: 'thead', 8 | tagName: 'thead' 9 | } 10 | }, 11 | { 12 | isComponent(el) { 13 | let result = ''; 14 | 15 | if (el.tagName == 'THEAD') { 16 | result = { type: 'thead' }; 17 | } 18 | 19 | return result; 20 | } 21 | } 22 | ); 23 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTableRow.js: -------------------------------------------------------------------------------- 1 | const Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: { 6 | ...Component.prototype.defaults, 7 | type: 'row', 8 | tagName: 'tr', 9 | draggable: ['thead', 'tbody', 'tfoot'], 10 | droppable: ['th', 'td'] 11 | }, 12 | 13 | initialize(o, opt) { 14 | Component.prototype.initialize.apply(this, arguments); 15 | 16 | // Clean the row from non cell components 17 | const cells = []; 18 | const components = this.get('components'); 19 | components.each(model => model.is('cell') && cells.push(model)); 20 | components.reset(cells); 21 | } 22 | }, 23 | { 24 | isComponent(el) { 25 | let result = ''; 26 | 27 | if (el.tagName == 'TR') { 28 | result = { type: 'row' }; 29 | } 30 | 31 | return result; 32 | } 33 | } 34 | ); 35 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentText.js: -------------------------------------------------------------------------------- 1 | const Component = require('./Component'); 2 | 3 | module.exports = Component.extend({ 4 | defaults: { 5 | ...Component.prototype.defaults, 6 | type: 'text', 7 | droppable: false, 8 | editable: true 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ComponentTextNode.js: -------------------------------------------------------------------------------- 1 | var Component = require('./Component'); 2 | 3 | module.exports = Component.extend( 4 | { 5 | defaults: _.extend({}, Component.prototype.defaults, { 6 | droppable: false, 7 | editable: true 8 | }), 9 | 10 | toHTML() { 11 | return this.get('content'); 12 | } 13 | }, 14 | { 15 | isComponent(el) { 16 | var result = ''; 17 | if (el.nodeType === 3) { 18 | result = { 19 | type: 'textnode', 20 | content: el.textContent 21 | }; 22 | } 23 | return result; 24 | } 25 | } 26 | ); 27 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/Components.js: -------------------------------------------------------------------------------- 1 | import { isEmpty } from 'underscore'; 2 | 3 | const Backbone = require('backbone'); 4 | 5 | module.exports = Backbone.Collection.extend({ 6 | initialize(models, opt = {}) { 7 | this.listenTo(this, 'add', this.onAdd); 8 | this.config = opt.config; 9 | this.em = opt.em; 10 | 11 | this.model = (attrs, options) => { 12 | var model; 13 | var df = opt.componentTypes; 14 | options.em = opt.em; 15 | options.config = opt.config; 16 | options.componentTypes = df; 17 | 18 | for (var it = 0; it < df.length; it++) { 19 | var dfId = df[it].id; 20 | if (dfId == attrs.type) { 21 | model = df[it].model; 22 | break; 23 | } 24 | } 25 | 26 | if (!model) { 27 | // get the last one 28 | model = df[df.length - 1].model; 29 | } 30 | 31 | return new model(attrs, options); 32 | }; 33 | }, 34 | 35 | add(models, opt = {}) { 36 | if (typeof models === 'string') { 37 | const cssc = this.em.get('CssComposer'); 38 | const parsed = this.em.get('Parser').parseHtml(models); 39 | models = parsed.html; 40 | 41 | if (parsed.css && cssc) { 42 | const { avoidUpdateStyle } = opt; 43 | const added = cssc.addCollection(parsed.css, { 44 | extend: 1, 45 | avoidUpdateStyle 46 | }); 47 | } 48 | } 49 | 50 | return Backbone.Collection.prototype.add.apply(this, [models, opt]); 51 | }, 52 | 53 | onAdd(model, c, opts) { 54 | const em = this.em; 55 | const style = model.getStyle(); 56 | const avoidInline = em && em.getConfig('avoidInlineStyle'); 57 | 58 | if ( 59 | !isEmpty(style) && 60 | !avoidInline && 61 | em && 62 | em.get && 63 | em.getConfig('forceClass') 64 | ) { 65 | const name = model.cid; 66 | const rule = em.get('CssComposer').setClassRule(name, style); 67 | model.setStyle({}); 68 | model.addClass(name); 69 | } 70 | } 71 | }); 72 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/Toolbar.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ToolbarButton = require('./ToolbarButton'); 3 | 4 | module.exports = Backbone.Collection.extend({ model: ToolbarButton }); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/model/ToolbarButton.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | command: '', 6 | attributes: {} 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentLinkView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentTextView'); 3 | 4 | module.exports = ComponentView.extend({ 5 | render(...args) { 6 | ComponentView.prototype.render.apply(this, args); 7 | 8 | // I need capturing instead of bubbling as bubbled clicks from other 9 | // children will execute the link event 10 | this.el.addEventListener('click', this.prevDef, true); 11 | 12 | return this; 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentMapView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentImageView'); 3 | 4 | module.exports = ComponentView.extend({ 5 | tagName: 'div', 6 | 7 | events: {}, 8 | 9 | initialize(o) { 10 | ComponentView.prototype.initialize.apply(this, arguments); 11 | this.classEmpty = this.ppfx + 'plh-map'; 12 | }, 13 | 14 | /** 15 | * Update the map on the canvas 16 | * @private 17 | */ 18 | updateSrc() { 19 | this.getIframe().src = this.model.get('src'); 20 | }, 21 | 22 | getIframe() { 23 | if (!this.iframe) { 24 | var ifrm = document.createElement('iframe'); 25 | ifrm.src = this.model.get('src'); 26 | ifrm.frameBorder = 0; 27 | ifrm.style.height = '100%'; 28 | ifrm.style.width = '100%'; 29 | ifrm.className = this.ppfx + 'no-pointer'; 30 | this.iframe = ifrm; 31 | } 32 | return this.iframe; 33 | }, 34 | 35 | render(...args) { 36 | ComponentView.prototype.render.apply(this, args); 37 | this.updateClasses(); 38 | this.el.appendChild(this.getIframe()); 39 | return this; 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentScriptView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentImageView'); 3 | 4 | module.exports = ComponentView.extend({ 5 | tagName: 'script', 6 | 7 | events: {}, 8 | 9 | render() { 10 | var model = this.model; 11 | var src = model.get('src'); 12 | var em = this.em; 13 | var scriptCount = em && em.get('scriptCount') ? em.get('scriptCount') : 0; 14 | var content = ''; 15 | 16 | // If it's an external script 17 | if (src) { 18 | var onload = model.get('onload'); 19 | var svar = 'script' + scriptCount; 20 | var svarNext = 'script' + (scriptCount + 1); 21 | content = 22 | 'var ' + 23 | svar + 24 | " = document.createElement('script');\n" + 25 | svar + 26 | '.onload = function(){\n' + 27 | (onload ? onload + '();\n' : '') + 28 | 'typeof ' + 29 | svarNext + 30 | "Start == 'function' && " + 31 | svarNext + 32 | 'Start();\n' + 33 | '};\n' + 34 | svar + 35 | ".src = '" + 36 | src + 37 | "';\n" + 38 | 'function ' + 39 | svar + 40 | 'Start() { document.body.appendChild(' + 41 | svar + 42 | '); };\n' + 43 | (!scriptCount ? svar + 'Start();' : ''); 44 | if (em) { 45 | em.set('scriptCount', scriptCount + 1); 46 | } 47 | } else { 48 | content = model.get('content'); 49 | } 50 | 51 | this.el.innerHTML = content; 52 | return this; 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentSvgView.js: -------------------------------------------------------------------------------- 1 | const ComponentView = require('./ComponentView'); 2 | 3 | module.exports = ComponentView.extend({ 4 | _createElement: function(tagName) { 5 | return document.createElementNS('http://www.w3.org/2000/svg', tagName); 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableBodyView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({}); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableCellView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({}); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableFootView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({}); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableHeadView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({}); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableRowView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({}); 5 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTableView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ComponentView = require('./ComponentView'); 3 | 4 | module.exports = ComponentView.extend({ 5 | events: {} 6 | }); 7 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ComponentTextNodeView.js: -------------------------------------------------------------------------------- 1 | module.exports = require('backbone').View.extend({}); 2 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ToolbarButtonView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.View.extend({ 4 | events() { 5 | return ( 6 | this.model.get('events') || { 7 | mousedown: 'handleClick' 8 | } 9 | ); 10 | }, 11 | 12 | attributes() { 13 | return this.model.get('attributes'); 14 | }, 15 | 16 | initialize(opts) { 17 | this.editor = opts.config.editor; 18 | }, 19 | 20 | handleClick(event) { 21 | event.preventDefault(); 22 | event.stopPropagation(); 23 | this.execCommand(event); 24 | }, 25 | 26 | execCommand(event) { 27 | const opts = { event }; 28 | const command = this.model.get('command'); 29 | const editor = this.editor; 30 | 31 | if (typeof command === 'function') { 32 | command(editor, null, opts); 33 | } 34 | 35 | if (typeof command === 'string') { 36 | editor.runCommand(command, opts); 37 | } 38 | }, 39 | 40 | render() { 41 | var config = this.editor.getConfig(); 42 | this.el.className += ' ' + config.stylePrefix + 'toolbar-item'; 43 | return this; 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /grapesjs/src/dom_components/view/ToolbarView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var DomainViews = require('domain_abstract/view/DomainViews'); 3 | var ToolbarButtonView = require('./ToolbarButtonView'); 4 | 5 | module.exports = DomainViews.extend({ 6 | itemView: ToolbarButtonView, 7 | 8 | initialize(opts) { 9 | this.config = { editor: opts.editor || '' }; 10 | this.listenTo(this.collection, 'reset', this.render); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /grapesjs/src/domain_abstract/ui/Input.js: -------------------------------------------------------------------------------- 1 | const $ = Backbone.$; 2 | 3 | module.exports = Backbone.View.extend({ 4 | events: { 5 | change: 'handleChange' 6 | }, 7 | 8 | template() { 9 | return ``; 10 | }, 11 | 12 | inputClass() { 13 | return `${this.ppfx}field`; 14 | }, 15 | 16 | holderClass() { 17 | return `${this.ppfx}input-holder`; 18 | }, 19 | 20 | initialize(opts = {}) { 21 | const ppfx = opts.ppfx || ''; 22 | this.opts = opts; 23 | this.ppfx = ppfx; 24 | this.em = opts.target || {}; 25 | this.listenTo(this.model, 'change:value', this.handleModelChange); 26 | }, 27 | 28 | /** 29 | * Fired when the element of the property is updated 30 | */ 31 | elementUpdated() { 32 | this.model.trigger('el:change'); 33 | }, 34 | 35 | /** 36 | * Set value to the input element 37 | * @param {string} value 38 | */ 39 | setValue(value) { 40 | const model = this.model; 41 | let val = value || model.get('defaults'); 42 | const input = this.getInputEl(); 43 | input && (input.value = val); 44 | }, 45 | 46 | /** 47 | * Updates the view when the model is changed 48 | * */ 49 | handleModelChange(model, value, opts) { 50 | this.setValue(value, opts); 51 | }, 52 | 53 | /** 54 | * Handled when the view is changed 55 | */ 56 | handleChange(e) { 57 | e.stopPropagation(); 58 | this.model.set('value', this.getInputEl().value); 59 | this.elementUpdated(); 60 | }, 61 | 62 | /** 63 | * Get the input element 64 | * @return {HTMLElement} 65 | */ 66 | getInputEl() { 67 | if (!this.inputEl) { 68 | const plh = this.model.get('defaults'); 69 | this.inputEl = $(``); 70 | } 71 | 72 | return this.inputEl.get(0); 73 | }, 74 | 75 | render() { 76 | const el = this.$el; 77 | el.addClass(this.inputClass()); 78 | el.html(this.template()); 79 | el.find(`.${this.holderClass()}`).append(this.getInputEl()); 80 | return this; 81 | } 82 | }); 83 | -------------------------------------------------------------------------------- /grapesjs/src/domain_abstract/view/DomainViews.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.View.extend({ 4 | // Default view 5 | itemView: '', 6 | 7 | // Defines the View per type 8 | itemsView: '', 9 | 10 | itemType: 'type', 11 | 12 | initialize(opts, config) { 13 | this.config = config || {}; 14 | }, 15 | 16 | /** 17 | * Add new model to the collection 18 | * @param {Model} model 19 | * @private 20 | * */ 21 | addTo(model) { 22 | this.add(model); 23 | }, 24 | 25 | /** 26 | * Render new model inside the view 27 | * @param {Model} model 28 | * @param {Object} fragment Fragment collection 29 | * @private 30 | * */ 31 | add(model, fragment) { 32 | var frag = fragment || null; 33 | var itemView = this.itemView; 34 | var typeField = model.get(this.itemType); 35 | if (this.itemsView && this.itemsView[typeField]) { 36 | itemView = this.itemsView[typeField]; 37 | } 38 | var view = new itemView( 39 | { 40 | model, 41 | config: this.config 42 | }, 43 | this.config 44 | ); 45 | var rendered = view.render().el; 46 | 47 | if (frag) frag.appendChild(rendered); 48 | else this.$el.append(rendered); 49 | }, 50 | 51 | render() { 52 | var frag = document.createDocumentFragment(); 53 | this.$el.empty(); 54 | 55 | if (this.collection.length) 56 | this.collection.each(function(model) { 57 | this.add(model, frag); 58 | }, this); 59 | 60 | this.$el.append(frag); 61 | return this; 62 | } 63 | }); 64 | -------------------------------------------------------------------------------- /grapesjs/src/editor/view/EditorView.js: -------------------------------------------------------------------------------- 1 | const $ = Backbone.$; 2 | 3 | module.exports = Backbone.View.extend({ 4 | initialize() { 5 | const model = this.model; 6 | model.view = this; 7 | this.conf = model.config; 8 | this.pn = model.get('Panels'); 9 | model.on('loaded', () => { 10 | this.pn.active(); 11 | this.pn.disableButtons(); 12 | model.runDefault(); 13 | setTimeout(() => model.trigger('load'), 0); 14 | }); 15 | }, 16 | 17 | render() { 18 | const model = this.model; 19 | const el = this.$el; 20 | const conf = this.conf; 21 | const contEl = $(conf.el || `body ${conf.container}`); 22 | const pfx = conf.stylePrefix; 23 | el.empty(); 24 | 25 | if (conf.width) contEl.css('width', conf.width); 26 | 27 | if (conf.height) contEl.css('height', conf.height); 28 | 29 | el.append(model.get('Canvas').render()); 30 | el.append(this.pn.render()); 31 | el.attr('class', `${pfx}editor ${pfx}one-bg ${pfx}two-color`); 32 | contEl 33 | .addClass(`${pfx}editor-cont`) 34 | .empty() 35 | .append(el); 36 | 37 | return this; 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /grapesjs/src/modal_dialog/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'mdl-', 3 | 4 | title: '', 5 | 6 | content: '', 7 | 8 | backdrop: true 9 | }; 10 | -------------------------------------------------------------------------------- /grapesjs/src/modal_dialog/model/Modal.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | title: '', 6 | content: '', 7 | open: false 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /grapesjs/src/navigator/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: '', 3 | 4 | // Specify the element to use as a container, string (query) or HTMLElement 5 | // With the empty value, nothing will be rendered 6 | appendTo: '', 7 | 8 | // Enable/Disable globally the possibility to sort layers 9 | sortable: 1, 10 | 11 | // Enable/Disable globally the possibility to hide layers 12 | hidable: 1, 13 | 14 | // Hide textnodes 15 | hideTextnode: 1, 16 | 17 | // Indicates if the wrapper is visible in layers 18 | showWrapper: 1 19 | }; 20 | -------------------------------------------------------------------------------- /grapesjs/src/navigator/index.js: -------------------------------------------------------------------------------- 1 | import defaults from './config/config'; 2 | import ItemView from './view/ItemView'; 3 | import ItemsView from './view/ItemsView'; 4 | import { isElement } from 'underscore'; 5 | 6 | module.exports = () => { 7 | let em; 8 | let layers; 9 | let config = {}; 10 | let View = ItemsView; 11 | 12 | return { 13 | name: 'LayerManager', 14 | 15 | init(opts = {}) { 16 | config = { ...defaults, ...opts }; 17 | config.stylePrefix = opts.pStylePrefix; 18 | em = config.em; 19 | 20 | return this; 21 | }, 22 | 23 | onLoad() { 24 | const collection = em.get('DomComponents').getComponents(); 25 | const parent = collection.parent; 26 | const options = { 27 | level: 0, 28 | config, 29 | opened: config.opened || {} 30 | }; 31 | 32 | // Show wrapper if requested 33 | if (config.showWrapper && parent) { 34 | View = ItemView; 35 | options.model = parent; 36 | } else { 37 | options.collection = collection; 38 | } 39 | 40 | layers = new View(options); 41 | em && em.on('component:selected', this.componentChanged); 42 | this.componentChanged(); 43 | }, 44 | 45 | postRender() { 46 | const elTo = config.appendTo; 47 | 48 | if (elTo) { 49 | const el = isElement(elTo) ? elTo : document.querySelector(elTo); 50 | el.appendChild(this.render()); 51 | } 52 | }, 53 | 54 | /** 55 | * Return the view of layers 56 | * @return {View} 57 | */ 58 | getAll() { 59 | return layers; 60 | }, 61 | 62 | /** 63 | * Triggered when the selected component is changed 64 | * @private 65 | */ 66 | componentChanged(e, md, opts = {}) { 67 | if (opts.fromLayers) return; 68 | const opened = em.get('opened'); 69 | const model = em.getSelected(); 70 | let parent = model && model.collection ? model.collection.parent : null; 71 | for (let cid in opened) opened[cid].set('open', 0); 72 | 73 | while (parent) { 74 | parent.set('open', 1); 75 | opened[parent.cid] = parent; 76 | parent = parent.collection ? parent.collection.parent : null; 77 | } 78 | }, 79 | 80 | render() { 81 | return layers.render().el; 82 | } 83 | }; 84 | }; 85 | -------------------------------------------------------------------------------- /grapesjs/src/panels/config/config.js: -------------------------------------------------------------------------------- 1 | var crc = 'create-comp'; 2 | var mvc = 'move-comp'; 3 | var swv = 'sw-visibility'; 4 | var expt = 'export-template'; 5 | var osm = 'open-sm'; 6 | var otm = 'open-tm'; 7 | var ola = 'open-layers'; 8 | var obl = 'open-blocks'; 9 | var ful = 'fullscreen'; 10 | var prv = 'preview'; 11 | 12 | module.exports = { 13 | stylePrefix: 'pn-', 14 | 15 | // Default panels fa-sliders for features 16 | defaults: [ 17 | { 18 | id: 'commands', 19 | buttons: [{}] 20 | }, 21 | { 22 | id: 'options', 23 | buttons: [ 24 | { 25 | active: true, 26 | id: swv, 27 | className: 'fa fa-square-o', 28 | command: swv, 29 | context: swv, 30 | attributes: { title: 'View components' } 31 | }, 32 | { 33 | id: prv, 34 | className: 'fa fa-eye', 35 | command: prv, 36 | context: prv, 37 | attributes: { title: 'Preview' } 38 | }, 39 | { 40 | id: ful, 41 | className: 'fa fa-arrows-alt', 42 | command: ful, 43 | context: ful, 44 | attributes: { title: 'Fullscreen' } 45 | }, 46 | { 47 | id: expt, 48 | className: 'fa fa-code', 49 | command: expt, 50 | attributes: { title: 'View code' } 51 | } 52 | ] 53 | }, 54 | { 55 | id: 'views', 56 | buttons: [ 57 | { 58 | id: osm, 59 | className: 'fa fa-paint-brush', 60 | command: osm, 61 | active: true, 62 | attributes: { title: 'Open Style Manager' } 63 | }, 64 | { 65 | id: otm, 66 | className: 'fa fa-cog', 67 | command: otm, 68 | attributes: { title: 'Settings' } 69 | }, 70 | { 71 | id: ola, 72 | className: 'fa fa-bars', 73 | command: ola, 74 | attributes: { title: 'Open Layer Manager' } 75 | }, 76 | { 77 | id: obl, 78 | className: 'fa fa-th-large', 79 | command: obl, 80 | attributes: { title: 'Open Blocks' } 81 | } 82 | ] 83 | } 84 | ], 85 | 86 | // Editor model 87 | em: null, 88 | 89 | // Delay before show children buttons (in milliseconds) 90 | delayBtnsShow: 300 91 | }; 92 | -------------------------------------------------------------------------------- /grapesjs/src/panels/model/Button.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | id: '', 6 | label: '', 7 | className: '', 8 | command: '', 9 | context: '', 10 | buttons: [], 11 | attributes: {}, 12 | options: {}, 13 | active: false, 14 | dragDrop: false, 15 | runDefaultCommand: true, 16 | stopDefaultCommand: false, 17 | disable: false 18 | }, 19 | 20 | initialize(options) { 21 | if (this.get('buttons').length) { 22 | var Buttons = require('./Buttons'); 23 | this.set('buttons', new Buttons(this.get('buttons'))); 24 | } 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /grapesjs/src/panels/model/Buttons.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Button = require('./Button'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | model: Button, 6 | 7 | /** 8 | * Deactivate all buttons, except one passed 9 | * @param {Object} except Model to ignore 10 | * @param {Boolean} r Recursive flag 11 | * 12 | * @return void 13 | * */ 14 | deactivateAllExceptOne(except, r) { 15 | this.forEach((model, index) => { 16 | if (model !== except) { 17 | model.set('active', false); 18 | if (r && model.get('buttons').length) 19 | model.get('buttons').deactivateAllExceptOne(except, r); 20 | } 21 | }); 22 | }, 23 | 24 | /** 25 | * Deactivate all buttons 26 | * @param {String} ctx Context string 27 | * 28 | * @return void 29 | * */ 30 | deactivateAll(ctx) { 31 | var context = ctx || ''; 32 | this.forEach((model, index) => { 33 | if (model.get('context') == context) { 34 | model.set('active', false); 35 | if (model.get('buttons').length) 36 | model.get('buttons').deactivateAll(context); 37 | } 38 | }); 39 | }, 40 | 41 | /** 42 | * Disables all buttons 43 | * @param {String} ctx Context string 44 | * 45 | * @return void 46 | * */ 47 | disableAllButtons(ctx) { 48 | var context = ctx || ''; 49 | this.forEach((model, index) => { 50 | if (model.get('context') == context) { 51 | model.set('disable', true); 52 | if (model.get('buttons').length) 53 | model.get('buttons').disableAllButtons(context); 54 | } 55 | }); 56 | }, 57 | 58 | /** 59 | * Disables all buttons, except one passed 60 | * @param {Object} except Model to ignore 61 | * @param {Boolean} r Recursive flag 62 | * 63 | * @return void 64 | * */ 65 | disableAllButtonsExceptOne(except, r) { 66 | this.forEach((model, index) => { 67 | if (model !== except) { 68 | model.set('disable', true); 69 | if (r && model.get('buttons').length) 70 | model.get('buttons').disableAllButtonsExceptOne(except, r); 71 | } 72 | }); 73 | } 74 | }); 75 | -------------------------------------------------------------------------------- /grapesjs/src/panels/model/Panel.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Buttons = require('./Buttons'); 3 | 4 | module.exports = Backbone.Model.extend({ 5 | defaults: { 6 | id: '', 7 | content: '', 8 | visible: true, 9 | buttons: [], 10 | attributes: {} 11 | }, 12 | 13 | initialize(options) { 14 | this.btn = this.get('buttons') || []; 15 | this.buttons = new Buttons(this.btn); 16 | this.set('buttons', this.buttons); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /grapesjs/src/panels/model/Panels.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var Panel = require('./Panel'); 3 | 4 | module.exports = Backbone.Collection.extend({ 5 | model: Panel 6 | }); 7 | -------------------------------------------------------------------------------- /grapesjs/src/panels/view/ButtonsView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var ButtonView = require('./ButtonView'); 3 | 4 | module.exports = Backbone.View.extend({ 5 | initialize(o) { 6 | this.opt = o || {}; 7 | this.config = this.opt.config || {}; 8 | this.pfx = this.config.stylePrefix || ''; 9 | this.parentM = this.opt.parentM || null; 10 | this.listenTo(this.collection, 'add', this.addTo); 11 | this.listenTo(this.collection, 'reset remove', this.render); 12 | this.className = this.pfx + 'buttons'; 13 | }, 14 | 15 | /** 16 | * Add to collection 17 | * @param Object Model 18 | * 19 | * @return Object 20 | * */ 21 | addTo(model) { 22 | this.addToCollection(model); 23 | }, 24 | 25 | /** 26 | * Add new object to collection 27 | * @param Object Model 28 | * @param Object Fragment collection 29 | * 30 | * @return Object Object created 31 | * */ 32 | addToCollection(model, fragmentEl) { 33 | var fragment = fragmentEl || null; 34 | var viewObject = ButtonView; 35 | 36 | var view = new viewObject({ 37 | model, 38 | config: this.config, 39 | parentM: this.parentM 40 | }); 41 | var rendered = view.render().el; 42 | 43 | if (fragment) { 44 | fragment.appendChild(rendered); 45 | } else { 46 | this.$el.append(rendered); 47 | } 48 | 49 | return rendered; 50 | }, 51 | 52 | render() { 53 | var fragment = document.createDocumentFragment(); 54 | this.$el.empty(); 55 | 56 | this.collection.each(function(model) { 57 | this.addToCollection(model, fragment); 58 | }, this); 59 | 60 | this.$el.append(fragment); 61 | this.$el.attr('class', _.result(this, 'className')); 62 | return this; 63 | } 64 | }); 65 | -------------------------------------------------------------------------------- /grapesjs/src/panels/view/PanelsView.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | var PanelView = require('./PanelView'); 3 | 4 | module.exports = Backbone.View.extend({ 5 | initialize(o) { 6 | this.opt = o || {}; 7 | this.config = this.opt.config || {}; 8 | this.pfx = this.config.stylePrefix || ''; 9 | this.listenTo(this.collection, 'add', this.addTo); 10 | this.listenTo(this.collection, 'reset', this.render); 11 | this.className = this.pfx + 'panels'; 12 | }, 13 | 14 | /** 15 | * Add to collection 16 | * @param Object Model 17 | * 18 | * @return Object 19 | * @private 20 | * */ 21 | addTo(model) { 22 | this.addToCollection(model); 23 | }, 24 | 25 | /** 26 | * Add new object to collection 27 | * @param Object Model 28 | * @param Object Fragment collection 29 | * @param integer Index of append 30 | * 31 | * @return Object Object created 32 | * @private 33 | * */ 34 | addToCollection(model, fragmentEl) { 35 | const fragment = fragmentEl || null; 36 | const config = this.config; 37 | const el = model.get('el'); 38 | const view = new PanelView({ 39 | el, 40 | model, 41 | config 42 | }); 43 | const rendered = view.render().el; 44 | const appendTo = model.get('appendTo'); 45 | 46 | // Do nothing if the panel was requested to be another element 47 | if (el) { 48 | } else if (appendTo) { 49 | var appendEl = document.querySelector(appendTo); 50 | appendEl.appendChild(rendered); 51 | } else { 52 | if (fragment) { 53 | fragment.appendChild(rendered); 54 | } else { 55 | this.$el.append(rendered); 56 | } 57 | } 58 | 59 | view.initResize(); 60 | return rendered; 61 | }, 62 | 63 | render() { 64 | const $el = this.$el; 65 | const frag = document.createDocumentFragment(); 66 | $el.empty(); 67 | this.collection.each(model => this.addToCollection(model, frag)); 68 | $el.append(frag); 69 | $el.attr('class', this.className); 70 | return this; 71 | } 72 | }); 73 | -------------------------------------------------------------------------------- /grapesjs/src/parser/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | textTags: ['br', 'b', 'i', 'u', 'a', 'ul', 'ol'] 3 | }; 4 | -------------------------------------------------------------------------------- /grapesjs/src/parser/index.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | var c = {}, 3 | defaults = require('./config/config'), 4 | parserCss = require('./model/ParserCss'), 5 | parserHtml = require('./model/ParserHtml'); 6 | var pHtml, pCss; 7 | 8 | return { 9 | compTypes: '', 10 | 11 | /** 12 | * Name of the module 13 | * @type {String} 14 | * @private 15 | */ 16 | name: 'Parser', 17 | 18 | /** 19 | * Initialize module. Automatically called with a new instance of the editor 20 | * @param {Object} config Configurations 21 | * @param {Array} [config.blocks=[]] Default blocks 22 | * @return {this} 23 | * @example 24 | * ... 25 | * { 26 | * blocks: [ 27 | * {id:'h1-block' label: 'Heading', content:'

...

'}, 28 | * ... 29 | * ], 30 | * } 31 | * ... 32 | */ 33 | init(config) { 34 | c = config || {}; 35 | for (var name in defaults) { 36 | if (!(name in c)) c[name] = defaults[name]; 37 | } 38 | pHtml = new parserHtml(c); 39 | pCss = new parserCss(c); 40 | return this; 41 | }, 42 | 43 | /** 44 | * Parse HTML string and return valid model 45 | * @param {string} str HTML string 46 | * @return {Object} 47 | */ 48 | parseHtml(str) { 49 | pHtml.compTypes = this.compTypes; 50 | return pHtml.parse(str, pCss); 51 | }, 52 | 53 | parseCss(str) { 54 | return pCss.parse(str); 55 | } 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /grapesjs/src/plugin_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [] 3 | }; 4 | -------------------------------------------------------------------------------- /grapesjs/src/plugin_manager/index.js: -------------------------------------------------------------------------------- 1 | module.exports = config => { 2 | var c = config || {}, 3 | defaults = require('./config/config'); 4 | 5 | // Set default options 6 | for (var name in defaults) { 7 | if (!(name in c)) c[name] = defaults[name]; 8 | } 9 | 10 | var plugins = {}; 11 | 12 | return { 13 | /** 14 | * Add new plugin. Plugins could not be overwritten 15 | * @param {string} id Plugin ID 16 | * @param {Function} plugin Function which contains all plugin logic 17 | * @return {Function} The plugin function 18 | * @example 19 | * PluginManager.add('some-plugin', function(editor){ 20 | * editor.Commands.add('new-command', { 21 | * run: function(editor, senderBtn){ 22 | * console.log('Executed new-command'); 23 | * } 24 | * }) 25 | * }); 26 | */ 27 | add(id, plugin) { 28 | if (plugins[id]) { 29 | return plugins[id]; 30 | } 31 | 32 | plugins[id] = plugin; 33 | return plugin; 34 | }, 35 | 36 | /** 37 | * Returns plugin by ID 38 | * @param {string} id Plugin ID 39 | * @return {Function|undefined} Plugin 40 | * @example 41 | * var plugin = PluginManager.get('some-plugin'); 42 | * plugin(editor); 43 | */ 44 | get(id) { 45 | return plugins[id]; 46 | }, 47 | 48 | /** 49 | * Returns object with all plugins 50 | * @return {Object} 51 | */ 52 | getAll() { 53 | return plugins; 54 | } 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /grapesjs/src/rich_text_editor/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'rte-', 3 | 4 | // If true, moves the toolbar below the element when the top canvas 5 | // edge is reached 6 | adjustToolbar: 1, 7 | 8 | // Default RTE actions 9 | actions: ['bold', 'italic', 'underline', 'strikethrough', 'link'] 10 | }; 11 | -------------------------------------------------------------------------------- /grapesjs/src/selector_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Style prefix 3 | stylePrefix: 'clm-', 4 | 5 | // Specify the element to use as a container, string (query) or HTMLElement 6 | // With the empty value, nothing will be rendered 7 | appendTo: '', 8 | 9 | // Default selectors 10 | selectors: [], 11 | 12 | // Label for selectors 13 | label: 'Classes', 14 | 15 | // Label for states 16 | statesLabel: '- State -', 17 | 18 | selectedLabel: 'Selected', 19 | 20 | // States 21 | states: [ 22 | { name: 'hover', label: 'Hover' }, 23 | { name: 'active', label: 'Click' }, 24 | { name: 'nth-of-type(2n)', label: 'Even/Odd' } 25 | ] 26 | }; 27 | -------------------------------------------------------------------------------- /grapesjs/src/selector_manager/model/Selector.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | const TYPE_CLASS = 1; 4 | const TYPE_ID = 2; 5 | 6 | const Selector = Backbone.Model.extend( 7 | { 8 | idAttribute: 'name', 9 | 10 | defaults: { 11 | name: '', 12 | 13 | label: '', 14 | 15 | // Type of the selector 16 | type: TYPE_CLASS, 17 | 18 | // If not active it's not selectable by the style manager (uncheckboxed) 19 | active: true, 20 | 21 | // Can't be seen by the style manager, therefore even by the user 22 | // Will be rendered only in export code 23 | private: false, 24 | 25 | // If true, can't be removed from the attacched element 26 | protected: false 27 | }, 28 | 29 | initialize() { 30 | const name = this.get('name'); 31 | const label = this.get('label'); 32 | 33 | if (!name) { 34 | this.set('name', label); 35 | } else if (!label) { 36 | this.set('label', name); 37 | } 38 | 39 | this.set('name', Selector.escapeName(this.get('name'))); 40 | }, 41 | 42 | /** 43 | * Get full selector name 44 | * @return {string} 45 | */ 46 | getFullName() { 47 | let init = ''; 48 | 49 | switch (this.get('type')) { 50 | case TYPE_CLASS: 51 | init = '.'; 52 | break; 53 | case TYPE_ID: 54 | init = '#'; 55 | break; 56 | } 57 | 58 | return init + this.get('name'); 59 | } 60 | }, 61 | { 62 | // All type selectors: https://developer.mozilla.org/it/docs/Web/CSS/CSS_Selectors 63 | // Here I define only what I need 64 | TYPE_CLASS, 65 | 66 | TYPE_ID, 67 | 68 | /** 69 | * Escape string 70 | * @param {string} name 71 | * @return {string} 72 | * @private 73 | */ 74 | escapeName(name) { 75 | return `${name}`.trim().replace(/([^a-z0-9\w-]+)/gi, '-'); 76 | } 77 | } 78 | ); 79 | 80 | module.exports = Selector; 81 | -------------------------------------------------------------------------------- /grapesjs/src/selector_manager/model/Selectors.js: -------------------------------------------------------------------------------- 1 | import { filter } from 'underscore'; 2 | const Selector = require('./Selector'); 3 | 4 | module.exports = require('backbone').Collection.extend({ 5 | model: Selector, 6 | 7 | getStyleable() { 8 | return filter( 9 | this.models, 10 | item => item.get('active') && !item.get('private') 11 | ); 12 | }, 13 | 14 | getValid() { 15 | return filter(this.models, item => !item.get('private')); 16 | }, 17 | 18 | getFullString(collection) { 19 | const result = []; 20 | const coll = collection || this; 21 | coll.forEach(selector => result.push(selector.getFullName())); 22 | return result.join('').trim(); 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /grapesjs/src/storage_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Prefix identifier that will be used inside storing and loading 3 | id: 'gjs-', 4 | 5 | // Enable/Disable autosaving 6 | autosave: 1, 7 | 8 | // Indicates if load data inside editor after init 9 | autoload: 1, 10 | 11 | // Indicates which storage to use. Available: local | remote 12 | type: 'local', 13 | 14 | // If autosave enabled, indicates how many steps (general changes to structure) 15 | // need to be done before save. Useful with remoteStorage to reduce remote calls 16 | stepsBeforeSave: 1, 17 | 18 | //Enable/Disable components model (JSON format) 19 | storeComponents: 1, 20 | 21 | //Enable/Disable styles model (JSON format) 22 | storeStyles: 1, 23 | 24 | //Enable/Disable saving HTML template 25 | storeHtml: 1, 26 | 27 | //Enable/Disable saving CSS template 28 | storeCss: 1, 29 | 30 | // ONLY FOR LOCAL STORAGE 31 | // If enabled, checks if browser supports Local Storage 32 | checkLocal: 1, 33 | 34 | // ONLY FOR REMOTE STORAGE 35 | // Custom parameters to pass with the remote storage request, eg. csrf token 36 | params: {}, 37 | 38 | // Custom headers for the remote storage request 39 | headers: {}, 40 | 41 | // Endpoint where to save all stuff 42 | urlStore: '', 43 | 44 | // Endpoint where to fetch data 45 | urlLoad: '', 46 | 47 | //Callback before request 48 | beforeSend(jqXHR, settings) {}, 49 | 50 | //Callback after request 51 | onComplete(jqXHR, status) {}, 52 | 53 | // set contentType paramater of $.ajax 54 | // true: application/json; charset=utf-8' 55 | // false: 'x-www-form-urlencoded' 56 | contentTypeJson: false 57 | }; 58 | -------------------------------------------------------------------------------- /grapesjs/src/storage_manager/model/LocalStorage.js: -------------------------------------------------------------------------------- 1 | var Backbone = require('backbone'); 2 | 3 | module.exports = Backbone.Model.extend({ 4 | defaults: { 5 | checkLocal: true 6 | }, 7 | 8 | /** 9 | * @private 10 | */ 11 | store(data, clb) { 12 | this.checkStorageEnvironment(); 13 | 14 | for (var key in data) localStorage.setItem(key, data[key]); 15 | 16 | if (typeof clb == 'function') { 17 | clb(); 18 | } 19 | }, 20 | 21 | /** 22 | * @private 23 | */ 24 | load(keys, clb) { 25 | this.checkStorageEnvironment(); 26 | var result = {}; 27 | 28 | for (var i = 0, len = keys.length; i < len; i++) { 29 | var value = localStorage.getItem(keys[i]); 30 | if (value) result[keys[i]] = value; 31 | } 32 | 33 | if (typeof clb == 'function') { 34 | clb(result); 35 | } 36 | 37 | return result; 38 | }, 39 | 40 | /** 41 | * @private 42 | */ 43 | remove(keys) { 44 | this.checkStorageEnvironment(); 45 | 46 | for (var i = 0, len = keys.length; i < len; i++) 47 | localStorage.removeItem(keys[i]); 48 | }, 49 | 50 | /** 51 | * Check storage environment 52 | * @private 53 | * */ 54 | checkStorageEnvironment() { 55 | if (this.get('checkLocal') && !localStorage) 56 | console.warn("Your browser doesn't support localStorage"); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'sm-', 3 | 4 | sectors: [], 5 | 6 | // Specify the element to use as a container, string (query) or HTMLElement 7 | // With the empty value, nothing will be rendered 8 | appendTo: '', 9 | 10 | // Text to show in case no element selected 11 | textNoElement: 'Select an element before using Style Manager', 12 | 13 | // Hide the property in case it's not stylable for the 14 | // selected component (each component has 'stylable' property) 15 | hideNotStylable: true, 16 | 17 | // Highlight changed properties of the selected component 18 | highlightChanged: true, 19 | 20 | // Highlight computed properties of the selected component 21 | highlightComputed: true, 22 | 23 | // Show computed properties of the selected component, if this value 24 | // is set to false, highlightComputed will not take effect 25 | showComputed: true, 26 | 27 | // Adds the possibility to clear property value from the target style 28 | clearProperties: 0, 29 | 30 | // Properties not to take in account for computed styles 31 | avoidComputed: ['width', 'height'] 32 | }; 33 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/Layer.js: -------------------------------------------------------------------------------- 1 | module.exports = Backbone.Model.extend({ 2 | defaults: { 3 | index: '', 4 | value: '', 5 | values: {}, 6 | active: false, 7 | preview: false, 8 | properties: [] 9 | }, 10 | 11 | initialize() { 12 | const Properties = require('./Properties'); 13 | const properties = this.get('properties'); 14 | var value = this.get('value'); 15 | this.set( 16 | 'properties', 17 | properties instanceof Properties ? properties : new Properties(properties) 18 | ); 19 | 20 | // If there is no value I'll try to get it from values 21 | // I need value setted to make preview working 22 | if (!value) { 23 | var val = ''; 24 | var values = this.get('values'); 25 | 26 | for (var prop in values) { 27 | val += ' ' + values[prop]; 28 | } 29 | 30 | this.set('value', val.trim()); 31 | } 32 | }, 33 | 34 | getPropertyValue(property) { 35 | let result = ''; 36 | this.get('properties').each(prop => { 37 | if (prop.get('property') == property) { 38 | result = prop.getFullValue(); 39 | } 40 | }); 41 | return result; 42 | }, 43 | 44 | getFullValue() { 45 | let result = []; 46 | this.get('properties').each(prop => result.push(prop.getFullValue())); 47 | return result.join(' '); 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/PropertyComposite.js: -------------------------------------------------------------------------------- 1 | const Property = require('./Property'); 2 | 3 | module.exports = Property.extend({ 4 | defaults: { 5 | ...Property.prototype.defaults, 6 | // 'background' is a good example where to make a difference 7 | // between detached and not 8 | // 9 | // - NOT detached (default) 10 | // background: url(..) no-repeat center ...; 11 | // - Detached 12 | // background-image: url(); 13 | // background-repeat: repeat; 14 | // ... 15 | detached: 0, 16 | 17 | // Array of sub properties 18 | properties: [], 19 | 20 | // Separator between properties 21 | separator: ' ' 22 | }, 23 | 24 | init() { 25 | const properties = this.get('properties') || []; 26 | const Properties = require('./Properties'); 27 | this.set('properties', new Properties(properties)); 28 | this.listenTo(this, 'change:value', this.updateValues); 29 | }, 30 | 31 | /** 32 | * Clear the value 33 | * @return {this} 34 | */ 35 | clearValue(opts = {}) { 36 | this.get('properties').each(property => property.clearValue()); 37 | return Property.prototype.clearValue.apply(this, arguments); 38 | }, 39 | 40 | /** 41 | * Update property values 42 | */ 43 | updateValues() { 44 | const values = this.getFullValue().split(this.get('separator')); 45 | this.get('properties').each((property, i) => { 46 | const len = values.length; 47 | // Try to get value from a shorthand: 48 | // 11px -> 11px 11px 11px 11xp 49 | // 11px 22px -> 11px 22px 11px 22xp 50 | const value = 51 | values[i] || values[i % len + (len != 1 && len % 2 ? 1 : 0)]; 52 | // There some issue with UndoManager 53 | //property.setValue(value, 0, {fromParent: 1}); 54 | }); 55 | }, 56 | 57 | /** 58 | * Returns default value 59 | * @param {Boolean} defaultProps Force to get defaults from properties 60 | * @return {string} 61 | */ 62 | getDefaultValue(defaultProps) { 63 | let value = this.get('defaults'); 64 | 65 | if (value && !defaultProps) { 66 | return value; 67 | } 68 | 69 | value = ''; 70 | const properties = this.get('properties'); 71 | properties.each((prop, index) => (value += `${prop.getDefaultValue()} `)); 72 | return value.trim(); 73 | }, 74 | 75 | getFullValue() { 76 | if (this.get('detached')) { 77 | return ''; 78 | } 79 | 80 | return this.get('properties').getFullValue(); 81 | } 82 | }); 83 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/PropertyInteger.js: -------------------------------------------------------------------------------- 1 | import { isUndefined } from 'underscore'; 2 | 3 | const Property = require('./Property'); 4 | const InputNumber = require('domain_abstract/ui/InputNumber'); 5 | 6 | module.exports = Property.extend({ 7 | defaults: { 8 | ...Property.prototype.defaults, 9 | // Array of units, eg. ['px', '%'] 10 | units: [], 11 | 12 | // Selected unit, eg. 'px' 13 | unit: '', 14 | 15 | // Integer value steps 16 | step: 1, 17 | 18 | // Minimum value 19 | min: '', 20 | 21 | // Maximum value 22 | max: '' 23 | }, 24 | 25 | init() { 26 | const unit = this.get('unit'); 27 | const units = this.get('units'); 28 | this.input = new InputNumber({ model: this }); 29 | 30 | if (units.length && !unit) { 31 | this.set('unit', units[0]); 32 | } 33 | }, 34 | 35 | clearValue(opts = {}) { 36 | this.set({ value: undefined, unit: undefined }, opts); 37 | return this; 38 | }, 39 | 40 | parseValue(val) { 41 | const parsed = Property.prototype.parseValue.apply(this, arguments); 42 | const { value, unit } = this.input.validateInputValue(parsed.value, { 43 | deepCheck: 1 44 | }); 45 | parsed.value = value; 46 | parsed.unit = unit; 47 | return parsed; 48 | }, 49 | 50 | getFullValue() { 51 | let value = this.get('value'); 52 | let unit = this.get('unit'); 53 | value = !isUndefined(value) ? value : ''; 54 | unit = !isUndefined(unit) && value ? unit : ''; 55 | value = `${value}${unit}`; 56 | return Property.prototype.getFullValue.apply(this, [value]); 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/PropertyRadio.js: -------------------------------------------------------------------------------- 1 | const Property = require('./Property'); 2 | 3 | module.exports = Property.extend({ 4 | defaults: { 5 | ...Property.prototype.defaults, 6 | // Array of options, eg. [{name: 'Label ', value: '100'}] 7 | options: [] 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/PropertySlider.js: -------------------------------------------------------------------------------- 1 | const Property = require('./PropertyInteger'); 2 | 3 | module.exports = Property.extend({ 4 | defaults: { 5 | ...Property.prototype.defaults, 6 | showInput: 1 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/PropertyStack.js: -------------------------------------------------------------------------------- 1 | const Property = require('./PropertyComposite'); 2 | const Layers = require('./Layers'); 3 | 4 | module.exports = Property.extend({ 5 | defaults: { 6 | ...Property.prototype.defaults, 7 | // Array of layers (which contain properties) 8 | layers: [], 9 | 10 | // Layer preview 11 | preview: 0 12 | }, 13 | 14 | init() { 15 | Property.prototype.init.apply(this, arguments); 16 | const layers = this.get('layers'); 17 | const layersColl = new Layers(layers); 18 | layersColl.properties = this.get('properties'); 19 | this.set('layers', layersColl); 20 | }, 21 | 22 | getFullValue() { 23 | return this.get('detached') ? '' : this.get('layers').getFullValue(); 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/model/Sectors.js: -------------------------------------------------------------------------------- 1 | const Sector = require('./Sector'); 2 | 3 | module.exports = require('backbone').Collection.extend({ 4 | model: Sector 5 | }); 6 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertiesView.js: -------------------------------------------------------------------------------- 1 | const PropertyView = require('./PropertyView'); 2 | const PropertyIntegerView = require('./PropertyIntegerView'); 3 | const PropertyRadioView = require('./PropertyRadioView'); 4 | const PropertySelectView = require('./PropertySelectView'); 5 | const PropertyColorView = require('./PropertyColorView'); 6 | const PropertyFileView = require('./PropertyFileView'); 7 | const PropertyCompositeView = require('./PropertyCompositeView'); 8 | const PropertyStackView = require('./PropertyStackView'); 9 | 10 | module.exports = Backbone.View.extend({ 11 | initialize(o) { 12 | this.config = o.config || {}; 13 | this.pfx = this.config.stylePrefix || ''; 14 | this.target = o.target || {}; 15 | this.propTarget = o.propTarget || {}; 16 | this.onChange = o.onChange; 17 | this.onInputRender = o.onInputRender || {}; 18 | this.customValue = o.customValue || {}; 19 | this.properties = []; 20 | const coll = this.collection; 21 | this.listenTo(coll, 'add', this.addTo); 22 | this.listenTo(coll, 'reset', this.render); 23 | }, 24 | 25 | addTo(model) { 26 | this.add(model); 27 | }, 28 | 29 | add(model, frag) { 30 | var view = new model.typeView({ 31 | model, 32 | name: model.get('name'), 33 | id: this.pfx + model.get('property'), 34 | target: this.target, 35 | propTarget: this.propTarget, 36 | onChange: this.onChange, 37 | onInputRender: this.onInputRender, 38 | config: this.config 39 | }); 40 | 41 | if (model.get('type') != 'composite') { 42 | view.customValue = this.customValue; 43 | } 44 | 45 | view.render(); 46 | const el = view.el; 47 | this.properties.push(view); 48 | 49 | if (frag) { 50 | frag.appendChild(el); 51 | } else { 52 | this.el.appendChild(el); 53 | } 54 | }, 55 | 56 | render() { 57 | this.properties = []; 58 | const fragment = document.createDocumentFragment(); 59 | this.collection.each(model => this.add(model, fragment)); 60 | this.$el.append(fragment); 61 | this.$el.attr('class', `${this.pfx}properties`); 62 | return this; 63 | } 64 | }); 65 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertyColorView.js: -------------------------------------------------------------------------------- 1 | const InputColor = require('domain_abstract/ui/InputColor'); 2 | 3 | module.exports = require('./PropertyIntegerView').extend({ 4 | setValue(value, opts = {}) { 5 | opts = { ...opts, silent: 1 }; 6 | this.inputInst.setValue(value, opts); 7 | }, 8 | 9 | onRender() { 10 | if (!this.input) { 11 | const ppfx = this.ppfx; 12 | const inputColor = new InputColor({ 13 | target: this.target, 14 | model: this.model, 15 | ppfx 16 | }); 17 | const input = inputColor.render(); 18 | this.el.querySelector(`.${ppfx}fields`).appendChild(input.el); 19 | this.$input = input.inputEl; 20 | this.$color = input.colorEl; 21 | this.input = this.$input.get(0); 22 | this.inputInst = input; 23 | } 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertyIntegerView.js: -------------------------------------------------------------------------------- 1 | const InputNumber = require('domain_abstract/ui/InputNumber'); 2 | const PropertyView = require('./PropertyView'); 3 | const $ = Backbone.$; 4 | let timeout; 5 | 6 | module.exports = PropertyView.extend({ 7 | templateInput() { 8 | return ''; 9 | }, 10 | 11 | init() { 12 | const model = this.model; 13 | this.listenTo(model, 'change:unit', this.modelValueChanged); 14 | this.listenTo(model, 'el:change', this.elementUpdated); 15 | }, 16 | 17 | setValue(value) { 18 | const parsed = this.model.parseValue(value); 19 | value = `${parsed.value}${parsed.unit}`; 20 | this.inputInst.setValue(value, { silent: 1 }); 21 | }, 22 | 23 | onRender() { 24 | const ppfx = this.ppfx; 25 | 26 | if (!this.input) { 27 | const input = this.model.input; 28 | input.ppfx = ppfx; 29 | input.render(); 30 | const fields = this.el.querySelector(`.${ppfx}fields`); 31 | fields.appendChild(input.el); 32 | this.$input = input.inputEl; 33 | this.unit = input.unitEl; 34 | this.$unit = $(this.unit); 35 | this.input = this.$input.get(0); 36 | this.inputInst = input; 37 | } 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertyRadioView.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./PropertyView').extend({ 2 | templateInput() { 3 | const pfx = this.pfx; 4 | const ppfx = this.ppfx; 5 | return ` 6 |
7 |
8 | `; 9 | }, 10 | 11 | onRender() { 12 | const pfx = this.pfx; 13 | const ppfx = this.ppfx; 14 | const itemCls = `${ppfx}radio-item-label`; 15 | const model = this.model; 16 | const prop = model.get('property'); 17 | const options = model.get('list') || model.get('options') || []; 18 | 19 | if (!this.input) { 20 | if (options && options.length) { 21 | let inputStr = ''; 22 | 23 | options.forEach(el => { 24 | let cl = el.className ? `${el.className} ${pfx}icon ${itemCls}` : ''; 25 | let id = `${prop}-${el.value}`; 26 | let labelTxt = el.name || el.value; 27 | let titleAttr = el.title ? `title="${el.title}"` : ''; 28 | inputStr += ` 29 |
30 | 33 | 36 |
37 | `; 38 | }); 39 | 40 | const inputHld = this.el.querySelector(`.${ppfx}field`); 41 | inputHld.innerHTML = `
${inputStr}
`; 42 | this.input = inputHld.firstChild; 43 | } 44 | } 45 | }, 46 | 47 | getInputValue() { 48 | const inputChk = this.getCheckedEl(); 49 | return inputChk ? inputChk.value : ''; 50 | }, 51 | 52 | getCheckedEl() { 53 | const input = this.getInputEl(); 54 | return input ? input.querySelector('input:checked') : ''; 55 | }, 56 | 57 | setValue(value) { 58 | const model = this.model; 59 | let val = value || model.get('value') || model.getDefaultValue(); 60 | const input = this.getInputEl(); 61 | const inputIn = input ? input.querySelector(`[value="${val}"]`) : ''; 62 | 63 | if (inputIn) { 64 | inputIn.checked = true; 65 | } else { 66 | const inputChk = this.getCheckedEl(); 67 | inputChk && (inputChk.checked = false); 68 | } 69 | } 70 | }); 71 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertySelectView.js: -------------------------------------------------------------------------------- 1 | const $ = Backbone.$; 2 | 3 | module.exports = require('./PropertyView').extend({ 4 | templateInput() { 5 | const pfx = this.pfx; 6 | const ppfx = this.ppfx; 7 | return ` 8 |
9 | 10 |
11 |
12 |
13 |
14 | `; 15 | }, 16 | 17 | onRender() { 18 | var pfx = this.pfx; 19 | const model = this.model; 20 | const options = model.get('list') || model.get('options') || []; 21 | 22 | if (!this.input) { 23 | let optionsStr = ''; 24 | 25 | options.forEach(option => { 26 | let name = option.name || option.value; 27 | let style = option.style ? option.style.replace(/"/g, '"') : ''; 28 | let styleAttr = style ? `style="${style}"` : ''; 29 | let value = option.value.replace(/"/g, '"'); 30 | optionsStr += ``; 31 | }); 32 | 33 | const inputH = this.el.querySelector(`#${pfx}input-holder`); 34 | inputH.innerHTML = ``; 35 | this.input = inputH.firstChild; 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /grapesjs/src/style_manager/view/PropertySliderView.js: -------------------------------------------------------------------------------- 1 | const Property = require('./PropertyIntegerView'); 2 | 3 | module.exports = Property.extend({ 4 | events() { 5 | return { 6 | ...Property.prototype.events, 7 | 'change [type=range]': 'inputValueChanged', 8 | 'input [type=range]': 'inputValueChangedSoft', 9 | change: '' 10 | }; 11 | }, 12 | 13 | templateInput(model) { 14 | const ppfx = this.ppfx; 15 | return ` 16 |
17 | 21 |
22 | `; 23 | }, 24 | 25 | getSliderEl() { 26 | if (!this.slider) { 27 | this.slider = this.el.querySelector('input[type=range]'); 28 | } 29 | 30 | return this.slider; 31 | }, 32 | 33 | inputValueChanged() { 34 | const model = this.model; 35 | const step = model.get('step'); 36 | this.getInputEl().value = this.getSliderEl().value; 37 | const value = this.getInputValue() - step; 38 | model.set('value', value, { avoidStore: 1 }).set('value', value + step); 39 | this.elementUpdated(); 40 | }, 41 | 42 | inputValueChangedSoft() { 43 | this.getInputEl().value = this.getSliderEl().value; 44 | this.model.set('value', this.getInputValue(), { avoidStore: 1 }); 45 | this.elementUpdated(); 46 | }, 47 | 48 | setValue(value) { 49 | this.getSliderEl().value = value; 50 | this.inputInst.setValue(value, { silent: 1 }); 51 | }, 52 | 53 | onRender() { 54 | Property.prototype.onRender.apply(this, arguments); 55 | 56 | if (!this.model.get('showInput')) { 57 | this.inputInst.el.style.display = 'none'; 58 | } 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/main-fonts.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/main-fonts.eot -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/main-fonts.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/main-fonts.ttf -------------------------------------------------------------------------------- /grapesjs/src/styles/fonts/main-fonts.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mavoweb/create/b5fca8f6331b368ab40acba48165733e33bc71e4/grapesjs/src/styles/fonts/main-fonts.woff -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_blocks.scss: -------------------------------------------------------------------------------- 1 | .#{$app-prefix}blocks-c { 2 | display: flex; 3 | flex-wrap: wrap; 4 | justify-content: flex-start; 5 | } 6 | 7 | .#{$app-prefix}block-categories { 8 | display: flex; 9 | flex-direction: column; 10 | } 11 | 12 | .#{$app-prefix}block-category { 13 | width: 100%; 14 | 15 | &.#{$app-prefix}open { 16 | @extend .#{$app-prefix}category-open; 17 | } 18 | 19 | .#{$app-prefix}title { 20 | @extend .#{$app-prefix}category-title; 21 | } 22 | 23 | .#{$app-prefix}caret-icon { 24 | margin-right: 5px; 25 | } 26 | } 27 | 28 | .#{$app-prefix}block { 29 | @include user-select(none); 30 | 31 | width: 45%; 32 | padding: 1em; 33 | box-sizing: border-box; 34 | min-height: 90px; 35 | cursor: all-scroll; 36 | font-size: 11px; 37 | font-weight: lighter; 38 | text-align: center; 39 | display: flex; 40 | flex-direction: column; 41 | justify-content: space-between; 42 | border: 1px solid rgba(0, 0, 0, 0.2); 43 | border-radius: 3px; 44 | margin: 10px 2.5% 5px; 45 | box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.15); 46 | transition: all 0.2s ease 0s; 47 | transition-property: box-shadow, color; 48 | 49 | &:hover { 50 | box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.15); 51 | } 52 | } 53 | 54 | .#{$app-prefix}block-svg { 55 | width: 54px; 56 | fill: currentColor; 57 | } 58 | 59 | .#{$app-prefix}block-svg-path { 60 | fill: currentColor; 61 | } 62 | 63 | .#{$app-prefix}block.fa { 64 | font-size: 2em; 65 | line-height: 2em; 66 | padding: 11px; 67 | } 68 | 69 | .#{$app-prefix}block-label { 70 | line-height: normal; 71 | font-size: 0.65rem; 72 | font-weight: normal; 73 | font-family: Helvetica, sans-serif; 74 | overflow: hidden; 75 | text-overflow: ellipsis; 76 | } 77 | 78 | .#{$app-prefix}block.#{$app-prefix}bdrag { 79 | width: auto; 80 | padding: 0; 81 | } 82 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_devices.scss: -------------------------------------------------------------------------------- 1 | .#{$app-prefix}devices-c { 2 | display: flex; 3 | align-items: center; 4 | padding: 3px; 5 | 6 | .#{$app-prefix}device-label { 7 | flex-grow: 2; 8 | text-align: left; 9 | margin-right: 10px; 10 | } 11 | 12 | .#{$app-prefix}select { 13 | flex-grow: 20; 14 | } 15 | 16 | .#{$app-prefix}add-trasp { 17 | flex-grow: 1; 18 | margin-left: 5px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_modal.scss: -------------------------------------------------------------------------------- 1 | .#{$mdl-prefix} { 2 | &backlayer { 3 | @include opacity(0.5); 4 | 5 | background-color: #000; 6 | position: absolute; 7 | top: 0; 8 | left: 0; 9 | z-index: 1; 10 | width: 100%; 11 | height: 100%; 12 | } 13 | 14 | &container { 15 | font-family: $mainFont; 16 | position: absolute; 17 | top: 0; 18 | left: 0; 19 | z-index: 10; 20 | width: 100%; 21 | height: 100%; 22 | } 23 | 24 | &dialog { 25 | text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.05); 26 | animation: #{$app-prefix}slide-down 0.215s; 27 | margin: 30px auto 0; 28 | max-width: 850px; 29 | width: 90%; 30 | border-radius: 3px; 31 | font-weight: lighter; 32 | position: relative; 33 | z-index: 2; 34 | } 35 | 36 | &title { 37 | font-size: 1rem; 38 | } 39 | 40 | &btn-close { 41 | @extend .btn-cl; 42 | 43 | position: absolute; 44 | right: 15px; 45 | top: 5px; 46 | } 47 | 48 | &active .#{$mdl-prefix}dialog { 49 | animation: #{$mdl-prefix}slide-down 0.216s; 50 | } 51 | 52 | &header, 53 | &content { 54 | padding: 10px 15px; 55 | clear: both; 56 | } 57 | 58 | &header { 59 | position: relative; 60 | border-bottom: 1px solid $mainDkColor; 61 | padding: 15px 15px 7px; 62 | } 63 | } 64 | 65 | .#{$app-prefix}export-dl::after { 66 | content: ""; 67 | clear: both; 68 | display: block; 69 | margin-bottom: 10px; 70 | } 71 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_panels.scss: -------------------------------------------------------------------------------- 1 | .#{$pn-prefix} { 2 | &panel { 3 | display: inline-block; 4 | position: absolute; 5 | box-sizing: border-box; 6 | text-align: center; 7 | padding: 5px; 8 | z-index: 3; 9 | 10 | .icon-undo, 11 | .icon-redo { 12 | font-size: 20px; 13 | height: 30px; 14 | width: 25px; 15 | } 16 | } 17 | 18 | &commands { 19 | width: (100% - $leftWidth); 20 | left: 0; 21 | top: 0; 22 | box-shadow: 0 0 5px $mainDkColor; 23 | } 24 | 25 | &options { 26 | right: $leftWidth; 27 | top: 0; 28 | } 29 | 30 | &views { 31 | border-bottom: 2px solid $mainDkColor; 32 | right: 0; 33 | width: $leftWidth; 34 | z-index: 4; 35 | 36 | &-container { 37 | height: 100%; 38 | padding: 42px 0 0; 39 | right: 0; 40 | width: $leftWidth; 41 | overflow: auto; 42 | box-shadow: 0 0 5px $mainDkColor; 43 | } 44 | } 45 | 46 | &buttons { 47 | align-items: center; 48 | display: flex; 49 | justify-content: space-between; 50 | } 51 | 52 | &btn { 53 | box-sizing: border-box; 54 | height: 30px; 55 | width: 30px; 56 | line-height: 21px; 57 | background-color: transparent; 58 | border: none; 59 | font-size: 18px; 60 | margin-right: 5px; 61 | border-radius: 2px; 62 | padding: 5px; 63 | position: relative; 64 | cursor: pointer; 65 | 66 | &.#{$pn-prefix}active { 67 | background-color: rgba(0, 0, 0, 0.15); 68 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.25) inset; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_rte.scss: -------------------------------------------------------------------------------- 1 | .#{$rte-prefix} { 2 | &toolbar { 3 | @extend .#{$app-prefix}no-user-select; 4 | 5 | border: 1px solid $mainDkColor; 6 | position: absolute; 7 | border-radius: 3px; 8 | z-index: 10; 9 | } 10 | 11 | &actionbar { 12 | display: flex; 13 | } 14 | 15 | &action { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | padding: 5px; 20 | min-width: 25px; 21 | border-right: 1px solid $mainDkColor; 22 | text-align: center; 23 | cursor: pointer; 24 | outline: none; 25 | 26 | &:last-child { 27 | border-right: none; 28 | } 29 | 30 | &:hover { 31 | background-color: $mainLhColor; 32 | } 33 | } 34 | 35 | &active { 36 | background-color: $mainDkColor; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_selectors.scss: -------------------------------------------------------------------------------- 1 | .#{$clm-prefix}field { 2 | @extend .#{$sm-prefix}field 3 | } 4 | 5 | .#{$clm-prefix}select { 6 | @extend .#{$sm-prefix}field.#{$sm-prefix}select; 7 | } 8 | 9 | .#{$clm-prefix}tags { 10 | @extend .#{$sm-prefix}sector; 11 | 12 | font-size: $fontSizeS; 13 | padding: 10px 5px; 14 | 15 | ##{$clm-prefix}label, 16 | ##{$clm-prefix}sel { 17 | padding: 7px 0; 18 | float: left; 19 | } 20 | 21 | ##{$clm-prefix}sel { 22 | font-style: italic; 23 | margin-left: 5px; 24 | } 25 | 26 | ##{$clm-prefix}status-c { 27 | float: right; 28 | } 29 | 30 | ##{$clm-prefix}tags-field { 31 | clear: both; 32 | padding: 5px; 33 | margin-bottom: 5px; 34 | } 35 | 36 | ##{$clm-prefix}tags-c { 37 | display: inline-block; 38 | vertical-align: top; 39 | } 40 | 41 | ##{$clm-prefix}add-tag { 42 | background-color: rgba(255, 255, 255, 0.15); 43 | border-radius: 2px; 44 | padding: $paddElClm; 45 | box-shadow: 1px 1px 0 rgba(255, 255, 255, 0.2) inset; 46 | border: 1px solid rgba(0, 0, 0, 0.15); 47 | cursor: pointer; 48 | } 49 | 50 | ##{$clm-prefix}new { 51 | @extend .#{$app-prefix}invis-invis; 52 | 53 | color: $fontColor; 54 | padding: $paddElClm; 55 | display: none; 56 | } 57 | 58 | .#{$clm-prefix}tag { 59 | display: inline-block; 60 | border-radius: 3px; 61 | margin: 0 3px 3px 0; 62 | padding: 5px; 63 | cursor: default; 64 | } 65 | 66 | ##{$clm-prefix}close { 67 | @extend .opac50; 68 | 69 | font-size: 20px; 70 | line-height: 0; 71 | cursor: pointer; 72 | color: rgba(255, 255, 255, 0.9); 73 | @extend .no-select; 74 | 75 | &:hover { 76 | @include opacity(0.7); 77 | } 78 | } 79 | 80 | ##{$clm-prefix}checkbox { 81 | color: rgba(255, 255, 255, 0.9); 82 | vertical-align: middle; 83 | cursor: pointer; 84 | font-size: 9px; 85 | } 86 | 87 | ##{$clm-prefix}tag-label { 88 | padding: 0 3px; 89 | cursor: text; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /grapesjs/src/styles/scss/_gjs_traits.scss: -------------------------------------------------------------------------------- 1 | .#{$app-prefix} { 2 | &traits-label { 3 | border-bottom: 1px solid $mainDkColor; 4 | font-weight: lighter; 5 | margin-bottom: 5px; 6 | padding: 10px; 7 | text-align: left; 8 | } 9 | } 10 | 11 | .#{$trt-prefix}header { 12 | font-weight: lighter; 13 | padding: 10px; 14 | } 15 | 16 | .#{$trt-prefix}trait { 17 | display: flex; 18 | justify-content: start; 19 | padding: 5px 10px; 20 | font-weight: lighter; 21 | 22 | &s { 23 | font-size: $fontSizeS; 24 | } 25 | 26 | .#{$app-prefix}label { 27 | width: 30%; 28 | text-align: left; 29 | } 30 | 31 | .#{$app-prefix}field { 32 | width: 70%; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stylePrefix: 'trt-', 3 | 4 | // Specify the element to use as a container, string (query) or HTMLElement 5 | // With the empty value, nothing will be rendered 6 | appendTo: '', 7 | 8 | labelContainer: 'Component settings', 9 | 10 | // Placeholder label for text input types 11 | labelPlhText: 'eg. Text here', 12 | 13 | // Placeholder label for href input 14 | labelPlhHref: 'eg. https://google.com', 15 | 16 | // Default options for the target input 17 | optionsTarget: [ 18 | { value: '', name: 'This window' }, 19 | { value: '_blank', name: 'New window' } 20 | ], 21 | 22 | // Text to show in case no element selected 23 | textNoElement: 'Select an element before using Trait Manager' 24 | }; 25 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/index.js: -------------------------------------------------------------------------------- 1 | import { defaults, isElement } from 'underscore'; 2 | 3 | const defaultOpts = require('./config/config'); 4 | const TraitsView = require('./view/TraitsView'); 5 | 6 | module.exports = () => { 7 | let c = {}; 8 | let TraitsViewer; 9 | 10 | return { 11 | TraitsView, 12 | 13 | /** 14 | * Name of the module 15 | * @type {String} 16 | * @private 17 | */ 18 | name: 'TraitManager', 19 | 20 | /** 21 | * Get configuration object 22 | * @return {Object} 23 | * @private 24 | */ 25 | getConfig() { 26 | return c; 27 | }, 28 | 29 | /** 30 | * Initialize module. Automatically called with a new instance of the editor 31 | * @param {Object} config Configurations 32 | */ 33 | init(config = {}) { 34 | c = config; 35 | defaults(c, defaultOpts); 36 | const ppfx = c.pStylePrefix; 37 | ppfx && (c.stylePrefix = `${ppfx}${c.stylePrefix}`); 38 | TraitsViewer = new TraitsView({ 39 | collection: [], 40 | editor: c.em, 41 | config: c 42 | }); 43 | return this; 44 | }, 45 | 46 | postRender() { 47 | const elTo = this.getConfig().appendTo; 48 | 49 | if (elTo) { 50 | const el = isElement(elTo) ? elTo : document.querySelector(elTo); 51 | el.appendChild(this.render()); 52 | } 53 | }, 54 | 55 | /** 56 | * 57 | * Get Traits viewer 58 | * @private 59 | */ 60 | getTraitsViewer() { 61 | return TraitsViewer; 62 | }, 63 | 64 | /** 65 | * Add new trait type 66 | * @param {string} name Type name 67 | * @param {Object} methods Object representing the trait 68 | */ 69 | addType(name, trait) { 70 | var itemView = TraitsViewer.itemView; 71 | TraitsViewer.itemsView[name] = itemView.extend(trait); 72 | }, 73 | 74 | /** 75 | * Get trait type 76 | * @param {string} name Type name 77 | * @return {Object} 78 | */ 79 | getType(name) { 80 | return TraitsViewer.itemsView[name]; 81 | }, 82 | 83 | render() { 84 | return TraitsViewer.render().el; 85 | } 86 | }; 87 | }; 88 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/model/Trait.js: -------------------------------------------------------------------------------- 1 | import { isUndefined } from 'underscore'; 2 | 3 | module.exports = require('backbone').Model.extend({ 4 | defaults: { 5 | type: 'text', // text, number, range, select 6 | label: '', 7 | name: '', 8 | min: '', 9 | max: '', 10 | unit: '', 11 | step: 1, 12 | value: '', 13 | target: '', 14 | default: '', 15 | placeholder: '', 16 | changeProp: 0, 17 | options: [] 18 | }, 19 | 20 | initialize() { 21 | const target = this.get('target'); 22 | const name = this.get('name'); 23 | const changeProp = this.get('changeProp'); 24 | 25 | if (target) { 26 | this.target = target; 27 | this.unset('target'); 28 | const targetEvent = changeProp 29 | ? `change:${name}` 30 | : `change:attributes:${name}`; 31 | this.listenTo(target, targetEvent, this.targetUpdated); 32 | } 33 | }, 34 | 35 | targetUpdated() { 36 | const value = this.getTargetValue(); 37 | !isUndefined(value) && this.set({ value }, { fromTarget: 1 }); 38 | }, 39 | 40 | getTargetValue() { 41 | const name = this.get('name'); 42 | const target = this.target; 43 | const prop = this.get('changeProp'); 44 | if (target) return prop ? target.get(name) : target.getAttributes()[name]; 45 | }, 46 | 47 | setTargetValue(value) { 48 | const target = this.target; 49 | const name = this.get('name'); 50 | if (isUndefined(value)) return; 51 | 52 | if (this.get('changeProp')) { 53 | target.set(name, value); 54 | } else { 55 | const attrs = { ...target.get('attributes') }; 56 | attrs[name] = value; 57 | target.set('attributes', attrs); 58 | } 59 | }, 60 | 61 | setValueFromInput(value, final = 1, opts = {}) { 62 | const toSet = { value }; 63 | this.set(toSet, { ...opts, avoidStore: 1 }); 64 | 65 | // Have to trigger the change 66 | if (final) { 67 | this.set('value', '', opts); 68 | this.set(toSet, opts); 69 | } 70 | }, 71 | 72 | /** 73 | * Get the initial value of the trait 74 | * @return {string} 75 | */ 76 | getInitValue() { 77 | const target = this.target; 78 | const name = this.get('name'); 79 | let value; 80 | 81 | if (target) { 82 | const attrs = target.get('attributes'); 83 | value = this.get('changeProp') ? target.get(name) : attrs[name]; 84 | } 85 | 86 | return value || this.get('value') || this.get('default'); 87 | } 88 | }); 89 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/model/TraitFactory.js: -------------------------------------------------------------------------------- 1 | module.exports = (config = {}) => ({ 2 | /** 3 | * Build props object by their name 4 | * @param {Array|string} props Array of properties name 5 | * @return {Array} 6 | */ 7 | build(props) { 8 | var objs = []; 9 | 10 | if (typeof props === 'string') props = [props]; 11 | 12 | for (var i = 0; i < props.length; i++) { 13 | var obj = {}; 14 | var prop = props[i]; 15 | obj.name = prop; 16 | 17 | // Define type 18 | switch (prop) { 19 | case 'target': 20 | obj.type = 'select'; 21 | break; 22 | } 23 | 24 | // Define placeholder 25 | switch (prop) { 26 | case 'title': 27 | case 'alt': 28 | case 'id': 29 | obj.placeholder = config.labelPlhText; 30 | break; 31 | case 'href': 32 | obj.placeholder = config.labelPlhHref; 33 | break; 34 | } 35 | 36 | // Define options 37 | switch (prop) { 38 | case 'target': 39 | obj.options = config.optionsTarget; 40 | break; 41 | } 42 | 43 | objs.push(obj); 44 | } 45 | 46 | return objs; 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/model/Traits.js: -------------------------------------------------------------------------------- 1 | import { isString, isArray } from 'underscore'; 2 | const Backbone = require('backbone'); 3 | const Trait = require('./Trait'); 4 | const TraitFactory = require('./TraitFactory'); 5 | 6 | module.exports = Backbone.Collection.extend({ 7 | model: Trait, 8 | 9 | initialize(coll, options = {}) { 10 | this.em = options.em || ''; 11 | this.listenTo(this, 'add', this.handleAdd); 12 | }, 13 | 14 | handleAdd(model) { 15 | const target = this.target; 16 | 17 | if (target) { 18 | model.target = target; 19 | } 20 | }, 21 | 22 | setTarget(target) { 23 | this.target = target; 24 | }, 25 | 26 | add(models, opt) { 27 | const em = this.em; 28 | 29 | // Use TraitFactory if necessary 30 | if (isString(models) || isArray(models)) { 31 | const tm = em && em.get && em.get('TraitManager'); 32 | const tmOpts = tm && tm.getConfig(); 33 | const tf = TraitFactory(tmOpts); 34 | 35 | if (isString(models)) { 36 | models = [models]; 37 | } 38 | 39 | for (var i = 0, len = models.length; i < len; i++) { 40 | const str = models[i]; 41 | const model = isString(str) ? tf.build(str)[0] : str; 42 | model.target = this.target; 43 | models[i] = model; 44 | } 45 | } 46 | 47 | return Backbone.Collection.prototype.add.apply(this, [models, opt]); 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/view/TraitCheckboxView.js: -------------------------------------------------------------------------------- 1 | var TraitView = require('./TraitView'); 2 | 3 | module.exports = TraitView.extend({ 4 | initialize(o) { 5 | TraitView.prototype.initialize.apply(this, arguments); 6 | var iconCls = this.ppfx + 'chk-icon'; 7 | this.tmpl = 8 | '
'; 15 | }, 16 | 17 | /** 18 | * Fires when the input is changed 19 | * @private 20 | */ 21 | onChange() { 22 | this.model.set('value', this.getInputEl().checked); 23 | }, 24 | 25 | /** 26 | * Returns input element 27 | * @return {HTMLElement} 28 | * @private 29 | */ 30 | getInputEl(...args) { 31 | var first; 32 | if (!this.$input) first = 1; 33 | var el = TraitView.prototype.getInputEl.apply(this, args); 34 | if (first) { 35 | var md = this.model; 36 | var name = md.get('name'); 37 | var target = this.target; 38 | if (md.get('changeProp')) { 39 | el.checked = target.get(name); 40 | } else { 41 | var attrs = target.get('attributes'); 42 | el.checked = !!attrs[name]; 43 | } 44 | } 45 | return el; 46 | } 47 | }); 48 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/view/TraitColorView.js: -------------------------------------------------------------------------------- 1 | var TraitView = require('./TraitView'); 2 | var InputColor = require('domain_abstract/ui/InputColor'); 3 | 4 | module.exports = TraitView.extend({ 5 | /** 6 | * Returns input element 7 | * @return {HTMLElement} 8 | * @private 9 | */ 10 | getInputEl() { 11 | if (!this.$input) { 12 | var value = this.getModelValue(); 13 | var inputColor = new InputColor({ 14 | target: this.config.em, 15 | contClass: this.ppfx + 'field-color', 16 | model: this.model, 17 | ppfx: this.ppfx 18 | }); 19 | this.input = inputColor.render(); 20 | this.$input = this.input.colorEl; 21 | value = value || ''; 22 | this.model.set('value', value).trigger('change:value'); 23 | this.input.setValue(value); 24 | } 25 | return this.$input.get(0); 26 | }, 27 | 28 | /** 29 | * Renders input 30 | * @private 31 | * */ 32 | renderField() { 33 | if (!this.$input) { 34 | this.getInputEl(); 35 | this.$el.append(this.input.el); 36 | } 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/view/TraitNumberView.js: -------------------------------------------------------------------------------- 1 | var TraitView = require('./TraitView'); 2 | var InputNumber = require('domain_abstract/ui/InputNumber'); 3 | 4 | module.exports = TraitView.extend({ 5 | getValueForTarget() { 6 | var model = this.model; 7 | var value = model.get('value'); 8 | var unit = model.get('unit'); 9 | return value ? value + unit : ''; 10 | }, 11 | 12 | /** 13 | * Returns input element 14 | * @return {HTMLElement} 15 | * @private 16 | */ 17 | getInputEl() { 18 | if (!this.$input) { 19 | var value = this.getModelValue(); 20 | var inputNumber = new InputNumber({ 21 | contClass: this.ppfx + 'field-int', 22 | model: this.model, 23 | ppfx: this.ppfx 24 | }); 25 | this.input = inputNumber.render(); 26 | this.$input = this.input.inputEl; 27 | this.$unit = this.input.unitEl; 28 | this.model.set('value', value); 29 | this.$input.val(value); 30 | } 31 | return this.$input.get(0); 32 | }, 33 | 34 | /** 35 | * Renders input 36 | * @private 37 | * */ 38 | renderField() { 39 | if (!this.$input) { 40 | this.$el.append(this.tmpl); 41 | this.getInputEl(); 42 | this.$el.find('.' + this.inputhClass).prepend(this.input.el); 43 | } 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/view/TraitSelectView.js: -------------------------------------------------------------------------------- 1 | const TraitView = require('./TraitView'); 2 | const $ = Backbone.$; 3 | 4 | module.exports = TraitView.extend({ 5 | initialize(o) { 6 | TraitView.prototype.initialize.apply(this, arguments); 7 | var ppfx = this.ppfx; 8 | this.tmpl = 9 | '
' + 14 | '
'; 19 | }, 20 | 21 | /** 22 | * Returns input element 23 | * @return {HTMLElement} 24 | * @private 25 | */ 26 | getInputEl() { 27 | if (!this.$input) { 28 | var md = this.model; 29 | var opts = md.get('options') || []; 30 | var input = ''; 51 | this.input = input; 52 | this.$input = $(this.input); 53 | 54 | var target = this.target; 55 | var name = md.get('name'); 56 | var val = md.get('value'); 57 | 58 | if (md.get('changeProp')) { 59 | val = val || target.get(name); 60 | } else { 61 | var attrs = target.get('attributes'); 62 | val = attrs[name]; 63 | } 64 | 65 | if (val) this.$input.val(val); 66 | } 67 | 68 | return this.$input.get(0); 69 | } 70 | }); 71 | -------------------------------------------------------------------------------- /grapesjs/src/trait_manager/view/TraitsView.js: -------------------------------------------------------------------------------- 1 | var DomainViews = require('domain_abstract/view/DomainViews'); 2 | var TraitView = require('./TraitView'); 3 | var TraitSelectView = require('./TraitSelectView'); 4 | var TraitCheckboxView = require('./TraitCheckboxView'); 5 | var TraitNumberView = require('./TraitNumberView'); 6 | var TraitColorView = require('./TraitColorView'); 7 | 8 | module.exports = DomainViews.extend({ 9 | itemView: TraitView, 10 | 11 | itemsView: { 12 | text: TraitView, 13 | number: TraitNumberView, 14 | select: TraitSelectView, 15 | checkbox: TraitCheckboxView, 16 | color: TraitColorView 17 | }, 18 | 19 | initialize(o = {}) { 20 | const config = o.config || {}; 21 | this.config = config; 22 | this.em = o.editor; 23 | this.pfx = config.stylePrefix || ''; 24 | this.ppfx = config.pStylePrefix || ''; 25 | this.className = this.pfx + 'traits'; 26 | const toListen = 'component:selected component:update:traits'; 27 | this.listenTo(this.em, toListen, this.updatedCollection); 28 | this.updatedCollection(); 29 | }, 30 | 31 | /** 32 | * Update view collection 33 | * @private 34 | */ 35 | updatedCollection() { 36 | const ppfx = this.ppfx; 37 | const comp = this.em.getSelected(); 38 | this.el.className = `${this.className} ${ppfx}one-bg ${ppfx}two-color`; 39 | 40 | if (comp) { 41 | this.collection = comp.get('traits'); 42 | this.render(); 43 | } 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /grapesjs/src/utils/fetch.js: -------------------------------------------------------------------------------- 1 | import Promise from 'promise-polyfill'; 2 | 3 | window.Promise = window.Promise || Promise; 4 | 5 | export default (typeof fetch == 'function' 6 | ? fetch.bind() 7 | : (url, options) => { 8 | return new Promise((res, rej) => { 9 | const req = new XMLHttpRequest(); 10 | req.open(options.method || 'get', url); 11 | req.withCredentials = options.credentials == 'include'; 12 | 13 | for (let k in options.headers || {}) { 14 | req.setRequestHeader(k, options.headers[k]); 15 | } 16 | 17 | req.onload = e => 18 | res({ 19 | status: req.status, 20 | statusText: req.statusText, 21 | text: () => Promise.resolve(req.responseText) 22 | }); 23 | req.onerror = rej; 24 | 25 | // Actually, fetch doesn't support onProgress feature 26 | if (req.upload && options.onProgress) { 27 | req.upload.onprogress = options.onProgress; 28 | } 29 | 30 | // Include body only if present 31 | options.body ? req.send(options.body) : req.send(); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /grapesjs/src/utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = () => { 2 | const Sorter = require('./Sorter'); 3 | const Resizer = require('./Resizer'); 4 | const Dragger = require('./Dragger'); 5 | 6 | return { 7 | /** 8 | * Name of the module 9 | * @type {String} 10 | * @private 11 | */ 12 | name: 'Utils', 13 | 14 | /** 15 | * Initialize module 16 | */ 17 | init() { 18 | return this; 19 | }, 20 | 21 | Sorter, 22 | Resizer, 23 | Dragger 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /grapesjs/src/utils/polyfills.js: -------------------------------------------------------------------------------- 1 | /** 2 | * File made for IE/Edge support 3 | * https://github.com/artf/grapesjs/issues/214 4 | */ 5 | 6 | export default () => { 7 | /** 8 | * Check if IE/Edge 9 | * @return {Boolean} 10 | */ 11 | const isIE = () => { 12 | let match; 13 | const agent = window.navigator.userAgent; 14 | const rules = [ 15 | ['edge', /Edge\/([0-9\._]+)/], 16 | ['ie', /MSIE\s(7\.0)/], 17 | ['ie', /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/], 18 | ['ie', /Trident\/7\.0.*rv\:([0-9\.]+).*\).*Gecko$/] 19 | ]; 20 | 21 | for (let i = 0; i < rules.length; i++) { 22 | const rule = rules[i]; 23 | match = rule[1].exec(agent); 24 | if (match) break; 25 | } 26 | 27 | return !!match; 28 | }; 29 | 30 | if (isIE()) { 31 | const originalCreateHTMLDocument = 32 | DOMImplementation.prototype.createHTMLDocument; 33 | DOMImplementation.prototype.createHTMLDocument = title => { 34 | if (!title) title = ''; 35 | return originalCreateHTMLDocument.apply(document.implementation, [title]); 36 | }; 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /grapesjs/test/helper.js: -------------------------------------------------------------------------------- 1 | import _ from 'underscore'; 2 | import expect from 'expect'; 3 | import sinon from 'sinon'; 4 | import { JSDOM } from 'jsdom'; 5 | 6 | const dom = new JSDOM('', { 7 | resources: 'usable' 8 | }); 9 | const window = dom.window; 10 | 11 | // Fix for the require of jquery 12 | var Module = require('module'); 13 | var originalRequire = Module.prototype.require; 14 | Module.prototype.require = function(name) { 15 | if (name == 'jquery') { 16 | return originalRequire.call(this, 'cash-dom'); 17 | } 18 | return originalRequire.apply(this, arguments); 19 | }; 20 | 21 | var localStorage = { 22 | getItem(key) { 23 | return this[key]; 24 | }, 25 | setItem(key, value) { 26 | this[key] = value; 27 | }, 28 | removeItem(key, value) { 29 | delete this[key]; 30 | } 31 | }; 32 | 33 | global.window = window; 34 | global.document = window.document; 35 | global.FormData = window.FormData; 36 | global._ = _; 37 | global.expect = expect; 38 | global.sinon = sinon; 39 | global.grapesjs = require('./../src'); 40 | global.Backbone = require('backbone'); 41 | global.localStorage = localStorage; 42 | global.SVGElement = global.Element; 43 | window.$ = Backbone.$; 44 | global.navigator = { userAgent: 'node.js' }; 45 | 46 | Object.keys(window).forEach(key => { 47 | if (!(key in global)) { 48 | global[key] = window[key]; 49 | } 50 | }); 51 | -------------------------------------------------------------------------------- /grapesjs/test/main.js: -------------------------------------------------------------------------------- 1 | //import grapesjs from './../src'; 2 | 3 | describe('Main', () => { 4 | describe('Startup', () => { 5 | it('Main object should be loaded', () => { 6 | expect(grapesjs).toExist(); 7 | }); 8 | }); 9 | 10 | const path = './specs/'; 11 | require(`${path}keymaps`); 12 | require(`${path}asset_manager`); 13 | require(`${path}block_manager`); 14 | require(`${path}code_manager`); 15 | require(`${path}commands`); 16 | require(`${path}css_composer`); 17 | require(`${path}device_manager`); 18 | require(`${path}dom_components`); 19 | require(`${path}modal`); 20 | require(`${path}panels`); 21 | require(`${path}parser`); 22 | require(`${path}plugin_manager`); 23 | require(`${path}selector_manager`); 24 | require(`${path}storage_manager`); 25 | require(`${path}style_manager`); 26 | require(`${path}trait_manager`); 27 | require(`${path}grapesjs`); 28 | }); 29 | -------------------------------------------------------------------------------- /grapesjs/test/specs/asset_manager/model/Asset.js: -------------------------------------------------------------------------------- 1 | var Asset = require('asset_manager/model/Asset'); 2 | 3 | module.exports = { 4 | run() { 5 | describe('Asset', () => { 6 | it('Object exists', () => { 7 | expect(Asset).toExist(); 8 | }); 9 | 10 | it('Has default values', () => { 11 | var obj = new Asset({}); 12 | expect(obj.get('type')).toNotExist(); 13 | expect(obj.get('src')).toNotExist(); 14 | expect(obj.getExtension()).toNotExist(); 15 | expect(obj.getFilename()).toNotExist(); 16 | }); 17 | 18 | it('Test getFilename', () => { 19 | var obj = new Asset({ type: 'image', src: 'ch/eck/t.e.s.t' }); 20 | expect(obj.getFilename()).toEqual('t.e.s.t'); 21 | var obj = new Asset({ type: 'image', src: 'ch/eck/1234abc' }); 22 | expect(obj.getFilename()).toEqual('1234abc'); 23 | }); 24 | 25 | it('Test getExtension', () => { 26 | var obj = new Asset({ type: 'image', src: 'ch/eck/t.e.s.t' }); 27 | expect(obj.getExtension()).toEqual('t'); 28 | var obj = new Asset({ type: 'image', src: 'ch/eck/1234abc.' }); 29 | expect(obj.getExtension()).toEqual(''); 30 | }); 31 | }); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /grapesjs/test/specs/asset_manager/model/AssetImage.js: -------------------------------------------------------------------------------- 1 | var AssetImage = require('asset_manager/model/AssetImage'); 2 | 3 | module.exports = { 4 | run() { 5 | describe('AssetImage', () => { 6 | it('Object exists', () => { 7 | expect(AssetImage).toExist(); 8 | }); 9 | 10 | it('Has default values', () => { 11 | var obj = new AssetImage({}); 12 | expect(obj.get('type')).toEqual('image'); 13 | expect(obj.get('src')).toNotExist(); 14 | expect(obj.get('unitDim')).toEqual('px'); 15 | expect(obj.get('height')).toEqual(0); 16 | expect(obj.get('width')).toEqual(0); 17 | expect(obj.getExtension()).toNotExist(); 18 | expect(obj.getFilename()).toNotExist(); 19 | }); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /grapesjs/test/specs/asset_manager/model/Assets.js: -------------------------------------------------------------------------------- 1 | var Assets = require('asset_manager/model/Assets'); 2 | 3 | module.exports = { 4 | run() { 5 | describe('Assets', () => { 6 | var obj; 7 | 8 | beforeEach(() => { 9 | obj = new Assets(); 10 | }); 11 | 12 | afterEach(() => { 13 | obj = null; 14 | }); 15 | 16 | it('Object exists', () => { 17 | expect(obj).toExist(); 18 | }); 19 | 20 | it('Collection is empty', () => { 21 | expect(obj.length).toEqual(0); 22 | }); 23 | }); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /grapesjs/test/specs/asset_manager/view/AssetImageView.js: -------------------------------------------------------------------------------- 1 | var AssetImageView = require('asset_manager/view/AssetImageView'); 2 | var AssetImage = require('asset_manager/model/AssetImage'); 3 | var Assets = require('asset_manager/model/Assets'); 4 | 5 | module.exports = { 6 | run() { 7 | let obj; 8 | 9 | describe('AssetImageView', () => { 10 | beforeEach(function() { 11 | var coll = new Assets(); 12 | var model = coll.add({ type: 'image', src: '/test' }); 13 | obj = new AssetImageView({ 14 | collection: new Assets(), 15 | config: {}, 16 | model 17 | }); 18 | document.body.innerHTML = '
'; 19 | document.body.querySelector('#fixtures').appendChild(obj.render().el); 20 | }); 21 | 22 | afterEach(function() { 23 | obj = null; 24 | document.body.innerHTML = ''; 25 | }); 26 | 27 | it('Object exists', () => { 28 | expect(AssetImageView).toExist(); 29 | }); 30 | 31 | describe('Asset should be rendered correctly', () => { 32 | it('Has preview box', function() { 33 | var $asset = obj.$el; 34 | expect($asset.find('.preview').length).toEqual(1); 35 | }); 36 | 37 | it('Has meta box', function() { 38 | var $asset = obj.$el; 39 | expect($asset.find('.meta').length).toEqual(1); 40 | }); 41 | 42 | it('Has close button', function() { 43 | var $asset = obj.$el; 44 | expect($asset.find('[data-toggle=asset-remove]').length).toEqual(1); 45 | }); 46 | }); 47 | 48 | it('Could be selected', function() { 49 | var spy = expect.spyOn(obj, 'updateTarget'); 50 | obj.$el.trigger('click'); 51 | expect(obj.$el.attr('class')).toInclude('highlight'); 52 | expect(spy).toHaveBeenCalled(); 53 | }); 54 | 55 | it('Could be chosen', function() { 56 | sinon.stub(obj, 'updateTarget'); 57 | var spy = expect.spyOn(obj, 'updateTarget'); 58 | obj.$el.trigger('dblclick'); 59 | expect(spy).toHaveBeenCalled(); 60 | //obj.updateTarget.calledOnce.should.equal(true); 61 | }); 62 | 63 | it('Could be removed', function() { 64 | var spy = sinon.spy(); 65 | obj.model.on('remove', spy); 66 | obj.onRemove({ stopImmediatePropagation() {} }); 67 | expect(spy.called).toEqual(true); 68 | }); 69 | }); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /grapesjs/test/specs/asset_manager/view/AssetView.js: -------------------------------------------------------------------------------- 1 | var AssetView = require('asset_manager/view/AssetView'); 2 | var Asset = require('asset_manager/model/Asset'); 3 | var Assets = require('asset_manager/model/Assets'); 4 | 5 | module.exports = { 6 | run() { 7 | describe('AssetView', () => { 8 | beforeEach(function() { 9 | var coll = new Assets(); 10 | var model = coll.add({ src: 'test' }); 11 | this.view = new AssetView({ 12 | config: {}, 13 | model 14 | }); 15 | document.body.innerHTML = '
'; 16 | document.body 17 | .querySelector('#fixtures') 18 | .appendChild(this.view.render().el); 19 | }); 20 | 21 | afterEach(function() { 22 | this.view.remove(); 23 | }); 24 | 25 | it('Object exists', () => { 26 | expect(AssetView).toExist(); 27 | }); 28 | 29 | it('Has correct prefix', function() { 30 | expect(this.view.pfx).toEqual(''); 31 | }); 32 | }); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /grapesjs/test/specs/block_manager/index.js: -------------------------------------------------------------------------------- 1 | var BlockManager = require('block_manager'); 2 | var BlocksView = require('./view/BlocksView'); 3 | 4 | describe('BlockManager', () => { 5 | describe('Main', () => { 6 | var obj; 7 | var idTest; 8 | var optsTest; 9 | 10 | beforeEach(() => { 11 | idTest = 'h1-block'; 12 | optsTest = { 13 | label: 'Heading', 14 | content: '

Test

' 15 | }; 16 | obj = new BlockManager().init(); 17 | obj.render(); 18 | }); 19 | 20 | afterEach(() => { 21 | obj = null; 22 | }); 23 | 24 | it('Object exists', () => { 25 | expect(obj).toExist(); 26 | }); 27 | 28 | it('No blocks inside', () => { 29 | expect(obj.getAll().length).toEqual(0); 30 | }); 31 | 32 | it('No categories inside', () => { 33 | expect(obj.getCategories().length).toEqual(0); 34 | }); 35 | 36 | it('Add new block', () => { 37 | var model = obj.add(idTest, optsTest); 38 | expect(obj.getAll().length).toEqual(1); 39 | }); 40 | 41 | it('Added block has correct data', () => { 42 | var model = obj.add(idTest, optsTest); 43 | expect(model.get('label')).toEqual(optsTest.label); 44 | expect(model.get('content')).toEqual(optsTest.content); 45 | }); 46 | 47 | it('Add block with attributes', () => { 48 | optsTest.attributes = { class: 'test' }; 49 | var model = obj.add(idTest, optsTest); 50 | expect(model.get('attributes').class).toEqual('test'); 51 | }); 52 | 53 | it('The id of the block is unique', () => { 54 | var model = obj.add(idTest, optsTest); 55 | var model2 = obj.add(idTest, { other: 'test' }); 56 | expect(model).toEqual(model2); 57 | }); 58 | 59 | it('Get block by id', () => { 60 | var model = obj.add(idTest, optsTest); 61 | var model2 = obj.get(idTest); 62 | expect(model).toEqual(model2); 63 | }); 64 | 65 | it('Render blocks', () => { 66 | obj.render(); 67 | expect(obj.getContainer()).toExist(); 68 | }); 69 | }); 70 | 71 | BlocksView.run(); 72 | }); 73 | -------------------------------------------------------------------------------- /grapesjs/test/specs/code_manager/index.js: -------------------------------------------------------------------------------- 1 | var CodeManager = require('code_manager'); 2 | var Models = require('./model/CodeModels'); 3 | 4 | describe('Code Manager', () => { 5 | describe('Main', () => { 6 | let obj; 7 | 8 | beforeEach(() => { 9 | obj = new CodeManager(); 10 | }); 11 | 12 | afterEach(() => { 13 | obj = null; 14 | }); 15 | 16 | it('Object exists', () => { 17 | expect(CodeManager).toExist(); 18 | }); 19 | 20 | it('No code generators inside', () => { 21 | expect(obj.getGenerators()).toEqual({}); 22 | }); 23 | 24 | it('No code viewers inside', () => { 25 | expect(obj.getViewers()).toEqual({}); 26 | }); 27 | 28 | it('Add and get code generator', () => { 29 | obj.addGenerator('test', 'gen'); 30 | expect(obj.getGenerator('test')).toEqual('gen'); 31 | }); 32 | 33 | it('Add and get code viewer', () => { 34 | obj.addViewer('test', 'view'); 35 | expect(obj.getViewer('test')).toEqual('view'); 36 | }); 37 | }); 38 | 39 | Models.run(); 40 | }); 41 | -------------------------------------------------------------------------------- /grapesjs/test/specs/commands/index.js: -------------------------------------------------------------------------------- 1 | var Commands = require('commands'); 2 | var Models = require('./model/CommandModels'); 3 | var CommandAbstract = require('./view/CommandAbstract'); 4 | 5 | describe('Commands', () => { 6 | describe('Main', () => { 7 | let obj; 8 | 9 | beforeEach(() => { 10 | obj = new Commands().init(); 11 | }); 12 | 13 | afterEach(() => { 14 | obj = null; 15 | }); 16 | 17 | it('No commands inside', () => { 18 | expect(obj.get('test')).toEqual(null); 19 | }); 20 | 21 | it('Push new command', () => { 22 | var comm = { test: 'test' }; 23 | obj.add('test', comm); 24 | expect(obj.get('test').test).toEqual('test'); 25 | }); 26 | 27 | it('Load default commands at init', () => { 28 | expect(obj.get('select-comp')).toNotEqual(null); 29 | expect(obj.get('create-comp')).toNotEqual(null); 30 | expect(obj.get('delete-comp')).toNotEqual(null); 31 | expect(obj.get('image-comp')).toNotEqual(null); 32 | expect(obj.get('move-comp')).toNotEqual(null); 33 | expect(obj.get('text-comp')).toNotEqual(null); 34 | expect(obj.get('insert-custom')).toNotEqual(null); 35 | expect(obj.get('export-template')).toNotEqual(null); 36 | expect(obj.get('sw-visibility')).toNotEqual(null); 37 | expect(obj.get('open-layers')).toNotEqual(null); 38 | expect(obj.get('open-sm')).toNotEqual(null); 39 | expect(obj.get('open-tm')).toNotEqual(null); 40 | expect(obj.get('open-blocks')).toNotEqual(null); 41 | expect(obj.get('open-assets')).toNotEqual(null); 42 | expect(obj.get('show-offset')).toNotEqual(null); 43 | expect(obj.get('select-parent')).toNotEqual(null); 44 | expect(obj.get('tlb-delete')).toNotEqual(null); 45 | expect(obj.get('tlb-clone')).toNotEqual(null); 46 | expect(obj.get('tlb-move')).toNotEqual(null); 47 | expect(obj.get('fullscreen')).toNotEqual(null); 48 | expect(obj.get('preview')).toNotEqual(null); 49 | expect(obj.get('resize')).toNotEqual(null); 50 | expect(obj.get('drag')).toNotEqual(null); 51 | }); 52 | 53 | it('Default commands after loadDefaultCommands', () => { 54 | obj.loadDefaultCommands(); 55 | expect(obj.get('select-comp')).toNotEqual(null); 56 | }); 57 | 58 | it('Commands module should not have toLoad property', () => { 59 | expect(obj.toLoad).toEqual(null); 60 | }); 61 | }); 62 | }); 63 | 64 | Models.run(); 65 | CommandAbstract.run(); 66 | -------------------------------------------------------------------------------- /grapesjs/test/specs/commands/model/CommandModels.js: -------------------------------------------------------------------------------- 1 | const Command = require('commands/model/Command'); 2 | const Commands = require('commands'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('Command', () => { 7 | let obj; 8 | 9 | beforeEach(() => { 10 | obj = new Command(); 11 | }); 12 | 13 | afterEach(() => { 14 | obj = null; 15 | }); 16 | 17 | it('Has id property', () => { 18 | expect(obj.has('id')).toEqual(true); 19 | }); 20 | }); 21 | 22 | describe('Commands', () => { 23 | var obj; 24 | 25 | beforeEach(() => { 26 | obj = new Commands(); 27 | }); 28 | 29 | afterEach(() => { 30 | obj = null; 31 | }); 32 | 33 | it('Object is ok', () => { 34 | expect(obj).toExist(); 35 | }); 36 | }); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /grapesjs/test/specs/device_manager/index.js: -------------------------------------------------------------------------------- 1 | const DeviceManager = require('device_manager'); 2 | const DevicesView = require('./view/DevicesView'); 3 | 4 | describe('DeviceManager', () => { 5 | describe('Main', () => { 6 | var obj; 7 | var testNameDevice; 8 | var testWidthDevice; 9 | 10 | beforeEach(() => { 11 | testNameDevice = 'Tablet'; 12 | testWidthDevice = '100px'; 13 | obj = new DeviceManager().init(); 14 | }); 15 | 16 | afterEach(() => { 17 | obj = null; 18 | }); 19 | 20 | it('Object exists', () => { 21 | expect(obj).toExist(); 22 | }); 23 | 24 | it('No device inside', () => { 25 | var coll = obj.getAll(); 26 | expect(coll.length).toEqual(0); 27 | }); 28 | 29 | it('Add new device', () => { 30 | var model = obj.add(testNameDevice, testWidthDevice); 31 | expect(obj.getAll().length).toEqual(1); 32 | }); 33 | 34 | it('Added device has correct data', () => { 35 | var model = obj.add(testNameDevice, testWidthDevice); 36 | expect(model.get('name')).toEqual(testNameDevice); 37 | expect(model.get('width')).toEqual(testWidthDevice); 38 | }); 39 | 40 | it('Add device width options', () => { 41 | var model = obj.add(testNameDevice, testWidthDevice, { opt: 'value' }); 42 | expect(model.get('opt')).toEqual('value'); 43 | }); 44 | 45 | it('The name of the device is unique', () => { 46 | var model = obj.add(testNameDevice, testWidthDevice); 47 | var model2 = obj.add(testNameDevice, '2px'); 48 | expect(model).toEqual(model2); 49 | }); 50 | 51 | it('Get device by name', () => { 52 | var model = obj.add(testNameDevice, testWidthDevice); 53 | var model2 = obj.get(testNameDevice); 54 | expect(model).toEqual(model2); 55 | }); 56 | 57 | it('Render devices', () => { 58 | expect(obj.render()).toExist(); 59 | }); 60 | }); 61 | 62 | DevicesView.run(); 63 | }); 64 | -------------------------------------------------------------------------------- /grapesjs/test/specs/device_manager/view/DevicesView.js: -------------------------------------------------------------------------------- 1 | const DevicesView = require('device_manager/view/DevicesView'); 2 | const Devices = require('device_manager/model/Devices'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('DevicesView', () => { 7 | var $fixtures; 8 | var $fixture; 9 | var model; 10 | var view; 11 | var editorModel; 12 | 13 | beforeEach(() => { 14 | model = new Devices([]); 15 | view = new DevicesView({ 16 | collection: model 17 | }); 18 | document.body.innerHTML = '
'; 19 | document.body.querySelector('#fixtures').appendChild(view.render().el); 20 | }); 21 | 22 | afterEach(() => { 23 | view.collection.reset(); 24 | }); 25 | 26 | it('The content is not empty', () => { 27 | expect(view.el.innerHTML).toExist(); 28 | }); 29 | 30 | it('No options without devices', () => { 31 | expect(view.getOptions()).toEqual(''); 32 | }); 33 | 34 | it('Render new button', () => { 35 | view.collection.add({}); 36 | expect(view.$el.html()).toExist(); 37 | }); 38 | 39 | describe('With configs', () => { 40 | beforeEach(() => { 41 | editorModel = new Backbone.Model(); 42 | model = new Devices([{ name: 'test1' }, { name: 'test2' }]); 43 | view = new DevicesView({ 44 | collection: model, 45 | config: { em: editorModel } 46 | }); 47 | document.body.innerHTML = '
'; 48 | document.body 49 | .querySelector('#fixtures') 50 | .appendChild(view.render().el); 51 | }); 52 | 53 | it('Update device on select change', () => { 54 | view.$el.find('select').val('test2'); 55 | view.updateDevice(); 56 | expect(view.config.em.get('device')).toEqual('test2'); 57 | }); 58 | 59 | it('Render options', () => { 60 | expect(view.getOptions()).toEqual( 61 | '' 62 | ); 63 | }); 64 | }); 65 | }); 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /grapesjs/test/specs/dom_components/view/ComponentImageView.js: -------------------------------------------------------------------------------- 1 | const ComponentImageView = require('dom_components/view/ComponentImageView'); 2 | const Component = require('dom_components/model/Component'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('ComponentImageView', () => { 7 | var model; 8 | var view; 9 | 10 | beforeEach(() => { 11 | model = new Component(); 12 | view = new ComponentImageView({ 13 | model 14 | }); 15 | document.body.innerHTML = '
'; 16 | document.body.querySelector('#fixtures').appendChild(view.render().el); 17 | }); 18 | 19 | afterEach(() => { 20 | view.remove(); 21 | }); 22 | 23 | it('Component empty', () => { 24 | expect(view.el.getAttribute('onmousedown')).toEqual('return false'); 25 | expect(view.el.getAttribute('class')).toEqual(view.classEmpty); 26 | }); 27 | 28 | it('TagName is ', () => { 29 | expect(view.el.tagName).toEqual('IMG'); 30 | }); 31 | 32 | it('Update src attribute', () => { 33 | model.set('src', './'); 34 | expect(view.el.getAttribute('src')).toEqual('./'); 35 | }); 36 | 37 | it('Renders correctly', () => { 38 | expect(view.render()).toExist(); 39 | }); 40 | }); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /grapesjs/test/specs/dom_components/view/ComponentTextView.js: -------------------------------------------------------------------------------- 1 | const ComponentTextView = require('dom_components/view/ComponentTextView'); 2 | const Component = require('dom_components/model/Component'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('ComponentTextView', () => { 7 | var fixtures; 8 | var model; 9 | var view; 10 | 11 | beforeEach(() => { 12 | model = new Component(); 13 | view = new ComponentTextView({ 14 | model 15 | }); 16 | document.body.innerHTML = '
'; 17 | fixtures = document.body.querySelector('#fixtures'); 18 | fixtures.appendChild(view.render().el); 19 | }); 20 | 21 | afterEach(() => { 22 | view.remove(); 23 | }); 24 | 25 | it('Component empty', () => { 26 | expect(fixtures.innerHTML).toEqual( 27 | '
' 28 | ); 29 | }); 30 | 31 | it('Input content is stored in model', () => { 32 | //view.enableEditing(); 33 | view.el.innerHTML = 'test'; 34 | //view.disableEditing(); 35 | //model.get('content').should.equal('test'); 36 | }); 37 | 38 | it('Init with content', () => { 39 | model = new Component({ content: 'test' }); 40 | view = new ComponentTextView({ model }); 41 | fixtures.appendChild(view.render().el); 42 | expect(view.el.innerHTML).toEqual('test'); 43 | }); 44 | }); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /grapesjs/test/specs/dom_components/view/ComponentsView.js: -------------------------------------------------------------------------------- 1 | const DomComponents = require('dom_components'); 2 | const ComponentsView = require('dom_components/view/ComponentsView'); 3 | const Components = require('dom_components/model/Components'); 4 | 5 | module.exports = { 6 | run() { 7 | describe('ComponentsView', () => { 8 | var $fixtures; 9 | var $fixture; 10 | var model; 11 | var view; 12 | var dcomp; 13 | var compOpts; 14 | 15 | beforeEach(() => { 16 | dcomp = new DomComponents(); 17 | compOpts = { 18 | componentTypes: dcomp.componentTypes 19 | }; 20 | model = new Components([], compOpts); 21 | view = new ComponentsView({ 22 | collection: model, 23 | componentTypes: dcomp.componentTypes 24 | }); 25 | document.body.innerHTML = '
'; 26 | document.body.querySelector('#fixtures').appendChild(view.render().el); 27 | }); 28 | 29 | afterEach(() => { 30 | view.collection.reset(); 31 | }); 32 | 33 | it('Collection is empty', () => { 34 | expect(view.$el.html()).toNotExist(); 35 | }); 36 | 37 | it('Add new component', () => { 38 | sinon.stub(view, 'addToCollection'); 39 | view.collection.add({}); 40 | expect(view.addToCollection.calledOnce).toEqual(true); 41 | }); 42 | 43 | it('Render new component', () => { 44 | view.collection.add({}); 45 | expect(view.$el.html()).toExist(); 46 | }); 47 | }); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /grapesjs/test/specs/keymaps/index.js: -------------------------------------------------------------------------------- 1 | const Editor = require('editor/model/Editor'); 2 | const Keymaps = require('keymaps'); 3 | 4 | describe('Keymaps', () => { 5 | describe('Main', () => { 6 | let em; 7 | let obj; 8 | 9 | beforeEach(() => { 10 | em = new Editor(); 11 | obj = new Keymaps().init({ em }); 12 | }); 13 | 14 | it('Object exists', () => { 15 | expect(obj).toExist(); 16 | }); 17 | 18 | it('No keymaps inside', () => { 19 | var coll = obj.getAll(); 20 | expect(coll).toEqual({}); 21 | }); 22 | 23 | it('Add new keymap', () => { 24 | const id = 'test'; 25 | const keys = 'ctrl+a'; 26 | const handler = () => {}; 27 | const model = obj.add(id, 'ctrl+a', handler); 28 | expect(obj.get(id)).toEqual({ id, keys, handler }); 29 | }); 30 | 31 | it('Add keymap event triggers', () => { 32 | let called = 0; 33 | em.on('keymap:add', () => (called = 1)); 34 | const model = obj.add('tes', 'ctrl+a'); 35 | expect(called).toEqual(1); 36 | }); 37 | 38 | it('Remove keymap', () => { 39 | const id = 'test'; 40 | const keys = 'ctrl+a'; 41 | const handler = () => {}; 42 | const model = obj.add(id, 'ctrl+a', handler); 43 | const removed = obj.remove(id); 44 | expect(obj.get(id)).toEqual(undefined); 45 | expect(obj.getAll()).toEqual({}); 46 | expect(removed).toEqual({ id, keys, handler }); 47 | }); 48 | 49 | it('Remove keymap event triggers', () => { 50 | let called = 0; 51 | em.on('keymap:remove', () => (called = 1)); 52 | const model = obj.add('tes', 'ctrl+a'); 53 | const removed = obj.remove('tes'); 54 | expect(called).toEqual(1); 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /grapesjs/test/specs/modal/index.js: -------------------------------------------------------------------------------- 1 | const Modal = require('modal_dialog'); 2 | const ModalView = require('./view/ModalView'); 3 | 4 | describe('Modal dialog', () => { 5 | describe('Main', () => { 6 | var obj; 7 | 8 | beforeEach(() => { 9 | obj = new Modal().init(); 10 | }); 11 | 12 | afterEach(() => { 13 | obj = null; 14 | }); 15 | 16 | it('Object exists', () => { 17 | expect(obj).toExist(); 18 | }); 19 | 20 | it('Is close by default', () => { 21 | expect(obj.isOpen()).toEqual(false); 22 | }); 23 | 24 | it('Title is empty', () => { 25 | expect(obj.getTitle()).toEqual(''); 26 | }); 27 | 28 | it('Content is empty', () => { 29 | expect(obj.getContent()).toEqual(''); 30 | }); 31 | 32 | it('Set title', () => { 33 | obj.setTitle('Test'); 34 | expect(obj.getTitle()).toEqual('Test'); 35 | }); 36 | 37 | it('Set content', () => { 38 | obj.setContent('Test'); 39 | expect(obj.getContent()).toEqual('Test'); 40 | }); 41 | 42 | it('Set HTML content', () => { 43 | obj.setContent('

Test

'); 44 | expect(obj.getContent()).toEqual('

Test

'); 45 | }); 46 | 47 | it('Open modal', () => { 48 | obj.open(); 49 | expect(obj.isOpen()).toEqual(true); 50 | }); 51 | 52 | it('Close modal', () => { 53 | obj.open(); 54 | obj.close(); 55 | expect(obj.isOpen()).toEqual(false); 56 | }); 57 | }); 58 | 59 | ModalView.run(); 60 | }); 61 | -------------------------------------------------------------------------------- /grapesjs/test/specs/modal/view/ModalView.js: -------------------------------------------------------------------------------- 1 | const ModalView = require('modal_dialog/view/ModalView'); 2 | const Modal = require('modal_dialog/model/Modal'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('ModalView', () => { 7 | var model; 8 | var view; 9 | var editorModel; 10 | 11 | beforeEach(() => { 12 | model = new Modal(); 13 | view = new ModalView({ 14 | model 15 | }); 16 | document.body.innerHTML = '
'; 17 | document.body.querySelector('#fixtures').appendChild(view.render().el); 18 | }); 19 | 20 | afterEach(() => { 21 | view = null; 22 | model = null; 23 | }); 24 | 25 | it('The content is not empty', () => { 26 | expect(view.el.innerHTML).toExist(); 27 | }); 28 | 29 | it('Get content', () => { 30 | expect(view.getContent()).toExist(); 31 | }); 32 | 33 | it('Update content', () => { 34 | model.set('content', 'test'); 35 | expect(view.getContent().get(0).innerHTML).toEqual('test'); 36 | }); 37 | 38 | it('Get title', () => { 39 | expect(view.getTitle()).toExist(); 40 | }); 41 | 42 | it('Update title', () => { 43 | model.set('title', 'test'); 44 | expect(view.getTitle().innerHTML).toEqual('test'); 45 | }); 46 | 47 | it('Close by default', () => { 48 | view.updateOpen(); 49 | expect(view.el.style.display).toEqual('none'); 50 | }); 51 | 52 | it('Open dialog', () => { 53 | model.set('open', 1); 54 | expect(view.el.style.display).toEqual(''); 55 | }); 56 | }); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /grapesjs/test/specs/panels/e2e/PanelsE2e.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run() { 3 | describe('E2E tests', () => { 4 | var fixtures; 5 | var fixture; 6 | var obj; 7 | var config; 8 | var editorName = 'panel-fixture'; 9 | 10 | before(() => { 11 | fixtures = $('
').appendTo('body'); 12 | }); 13 | 14 | beforeEach(() => { 15 | obj = grapesjs; 16 | config = { 17 | container: '#' + editorName, 18 | storageManager: { autoload: 0, type: 'none' } 19 | }; 20 | fixture = $('
'); 21 | fixture.empty().appendTo(fixtures); 22 | }); 23 | 24 | afterEach(() => { 25 | obj = null; 26 | config = null; 27 | fixture.remove(); 28 | }); 29 | 30 | after(() => { 31 | //fixture.remove(); 32 | }); 33 | 34 | it('Command is correctly executed on button click', () => { 35 | var commandId = 'command-test'; 36 | config.commands = { 37 | defaults: [ 38 | { 39 | id: commandId, 40 | run(ed, caller) { 41 | ed.testValue = 'testValue'; 42 | caller.set('active', false); 43 | } 44 | } 45 | ] 46 | }; 47 | config.panels = { 48 | defaults: [ 49 | { 50 | id: 'toolbar-test', 51 | buttons: [ 52 | { 53 | id: 'button-test', 54 | className: 'fa fa-smile-o', 55 | command: commandId 56 | } 57 | ] 58 | } 59 | ] 60 | }; 61 | var editor = obj.init(config); 62 | editor.testValue = ''; 63 | var button = editor.Panels.getButton('toolbar-test', 'button-test'); 64 | button.set('active', 1); 65 | expect(editor.testValue).toEqual('testValue'); 66 | expect(button.get('active')).toEqual(false); 67 | }); 68 | }); 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /grapesjs/test/specs/panels/view/ButtonsView.js: -------------------------------------------------------------------------------- 1 | const ButtonsView = require('panels/view/ButtonsView'); 2 | const Buttons = require('panels/model/Buttons'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('ButtonsView', () => { 7 | var fixtures; 8 | var model; 9 | var view; 10 | 11 | beforeEach(() => { 12 | model = new Buttons([]); 13 | view = new ButtonsView({ 14 | collection: model 15 | }); 16 | document.body.innerHTML = '
'; 17 | fixtures = document.body.querySelector('#fixtures'); 18 | fixtures.appendChild(view.render().el); 19 | }); 20 | 21 | afterEach(() => { 22 | view.collection.reset(); 23 | }); 24 | 25 | it('Collection is empty', () => { 26 | expect(view.$el.html()).toEqual(''); 27 | }); 28 | 29 | it('Add new button', () => { 30 | sinon.stub(view, 'addToCollection'); 31 | view.collection.add({}); 32 | expect(view.addToCollection.calledOnce).toEqual(true); 33 | }); 34 | 35 | it('Render new button', () => { 36 | view.collection.add({}); 37 | expect(view.$el.html()).toExist(); 38 | }); 39 | }); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /grapesjs/test/specs/panels/view/PanelView.js: -------------------------------------------------------------------------------- 1 | const PanelView = require('panels/view/PanelView'); 2 | const Panel = require('panels/model/Panel'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('PanelView', () => { 7 | var fixtures; 8 | var model; 9 | var view; 10 | 11 | beforeEach(() => { 12 | model = new Panel(); 13 | view = new PanelView({ 14 | model 15 | }); 16 | document.body.innerHTML = '
'; 17 | fixtures = document.body.querySelector('#fixtures'); 18 | fixtures.appendChild(view.render().el); 19 | }); 20 | 21 | afterEach(() => { 22 | view.remove(); 23 | }); 24 | 25 | it('Panel empty', () => { 26 | fixtures.firstChild.className = ''; 27 | expect(fixtures.innerHTML).toEqual('
'); 28 | }); 29 | 30 | it('Append content', () => { 31 | model.set('appendContent', 'test'); 32 | model.set('appendContent', 'test2'); 33 | expect(view.$el.html()).toEqual('testtest2'); 34 | }); 35 | 36 | it('Update content', () => { 37 | model.set('content', 'test'); 38 | model.set('content', 'test2'); 39 | expect(view.$el.html()).toEqual('test2'); 40 | }); 41 | 42 | describe('Init with options', () => { 43 | beforeEach(() => { 44 | model = new Panel({ 45 | buttons: [{}] 46 | }); 47 | view = new PanelView({ 48 | model 49 | }); 50 | document.body.innerHTML = '
'; 51 | fixtures = document.body.querySelector('#fixtures'); 52 | fixtures.appendChild(view.render().el); 53 | }); 54 | 55 | afterEach(() => { 56 | view.remove(); 57 | }); 58 | }); 59 | }); 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /grapesjs/test/specs/panels/view/PanelsView.js: -------------------------------------------------------------------------------- 1 | const PanelsView = require('panels/view/PanelsView'); 2 | const Panels = require('panels/model/Panels'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('PanelsView', () => { 7 | var fixtures; 8 | var $fixture; 9 | var model; 10 | var view; 11 | 12 | beforeEach(() => { 13 | model = new Panels([]); 14 | view = new PanelsView({ 15 | collection: model 16 | }); 17 | document.body.innerHTML = '
'; 18 | fixtures = document.body.querySelector('#fixtures'); 19 | fixtures.appendChild(view.render().el); 20 | }); 21 | 22 | afterEach(() => { 23 | view.collection.reset(); 24 | }); 25 | 26 | it('Collection is empty', () => { 27 | expect(view.$el.html()).toEqual(''); 28 | }); 29 | 30 | it('Add new panel', () => { 31 | sinon.stub(view, 'addToCollection'); 32 | view.collection.add({}); 33 | expect(view.addToCollection.calledOnce).toEqual(true); 34 | }); 35 | 36 | it('Render new panel', () => { 37 | view.collection.add({}); 38 | expect(view.$el.html()).toExist(); 39 | }); 40 | }); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /grapesjs/test/specs/parser/index.js: -------------------------------------------------------------------------------- 1 | const ParserHtml = require('./model/ParserHtml'); 2 | const ParserCss = require('./model/ParserCss'); 3 | 4 | describe('Parser', () => { 5 | ParserHtml.run(); 6 | ParserCss.run(); 7 | }); 8 | -------------------------------------------------------------------------------- /grapesjs/test/specs/plugin_manager/index.js: -------------------------------------------------------------------------------- 1 | const PluginManager = require('plugin_manager'); 2 | 3 | describe('PluginManager', () => { 4 | describe('Main', () => { 5 | var obj; 6 | var val; 7 | var testPlugin = e => { 8 | val = e; 9 | }; 10 | 11 | beforeEach(() => { 12 | obj = new PluginManager(); 13 | }); 14 | 15 | afterEach(() => { 16 | obj = null; 17 | }); 18 | 19 | it('Object exists', () => { 20 | expect(obj).toExist(); 21 | }); 22 | 23 | it('No plugins inside', () => { 24 | expect(obj.getAll()).toEqual({}); 25 | }); 26 | 27 | it('Add new plugin', () => { 28 | obj.add('test', testPlugin); 29 | expect(obj.get('test')).toExist(); 30 | }); 31 | 32 | it('Added plugin is working', () => { 33 | obj.add('test', testPlugin); 34 | var plugin = obj.get('test'); 35 | plugin('tval'); 36 | expect(val).toEqual('tval'); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /grapesjs/test/specs/selector_manager/model/SelectorModels.js: -------------------------------------------------------------------------------- 1 | const Selector = require('selector_manager/model/Selector'); 2 | const Selectors = require('selector_manager/model/Selectors'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('Selector', () => { 7 | var obj; 8 | 9 | beforeEach(() => { 10 | obj = new Selector(); 11 | }); 12 | 13 | afterEach(() => { 14 | obj = null; 15 | }); 16 | 17 | it('Has name property', () => { 18 | expect(obj.has('name')).toEqual(true); 19 | }); 20 | 21 | it('Has label property', () => { 22 | expect(obj.has('label')).toEqual(true); 23 | }); 24 | 25 | it('Has active property', () => { 26 | expect(obj.has('active')).toEqual(true); 27 | }); 28 | 29 | it('escapeName test', () => { 30 | expect(Selector.escapeName('@Te sT*')).toEqual('-Te-sT-'); 31 | }); 32 | 33 | it('Name is corrected at instantiation', () => { 34 | obj = new Selector({ name: '@Te sT*' }); 35 | expect(obj.get('name')).toEqual('-Te-sT-'); 36 | }); 37 | }); 38 | 39 | describe('Selectors', () => { 40 | var obj; 41 | 42 | beforeEach(() => { 43 | obj = new Selectors(); 44 | }); 45 | 46 | it('Creates collection item correctly', () => { 47 | var c = new Selectors(); 48 | var m = c.add({}); 49 | expect(m instanceof Selector).toEqual(true); 50 | }); 51 | 52 | it('getFullString with single class', () => { 53 | obj.add({ name: 'test' }); 54 | expect(obj.getFullString()).toEqual('.test'); 55 | }); 56 | 57 | it('getFullString with multiple classes', () => { 58 | obj.add([{ name: 'test' }, { name: 'test2' }]); 59 | expect(obj.getFullString()).toEqual('.test.test2'); 60 | }); 61 | 62 | it('getFullString with mixed selectors', () => { 63 | obj.add([{ name: 'test' }, { name: 'test2', type: Selector.TYPE_ID }]); 64 | expect(obj.getFullString()).toEqual('.test#test2'); 65 | }); 66 | }); 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /grapesjs/test/specs/style_manager/view/LayerView.js: -------------------------------------------------------------------------------- 1 | const LayerView = require('style_manager/view/LayerView'); 2 | const Layers = require('style_manager/model/Layers'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('LayerView', () => { 7 | var component; 8 | var fixtures; 9 | var target; 10 | var model; 11 | var view; 12 | 13 | beforeEach(() => { 14 | var coll = new Layers(); 15 | model = coll.add({}); 16 | view = new LayerView({ 17 | model 18 | }); 19 | document.body.innerHTML = '
'; 20 | fixtures = document.body.firstChild; 21 | fixtures.appendChild(view.render().el); 22 | }); 23 | 24 | after(() => { 25 | component = null; 26 | view = null; 27 | model = null; 28 | }); 29 | 30 | it('Rendered correctly', () => { 31 | var layer = view.el; 32 | expect(fixtures.querySelector('.layer')).toExist(); 33 | expect(layer.querySelector('#label')).toExist(); 34 | expect(layer.querySelector('#close-layer')).toExist(); 35 | expect(view.getPropertiesWrapper()).toExist(); 36 | expect(view.getPreviewEl()).toExist(); 37 | }); 38 | 39 | it('Is not active by default', () => { 40 | expect(view.$el.hasClass('active')).toEqual(false); 41 | }); 42 | 43 | it('Is possible to activate it', () => { 44 | view.model.set('active', 1); 45 | expect(view.$el.hasClass('active')).toEqual(true); 46 | }); 47 | 48 | it('Is possible to activate it with active()', () => { 49 | view.active(); 50 | expect(view.$el.hasClass('active')).toEqual(true); 51 | }); 52 | 53 | it('No preview', () => { 54 | var style = view.el.querySelector('#preview').style; 55 | expect(style.cssText).toNotExist(); 56 | }); 57 | }); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /grapesjs/test/specs/style_manager/view/SectorsView.js: -------------------------------------------------------------------------------- 1 | const SectorsView = require('style_manager/view/SectorsView'); 2 | const Sectors = require('style_manager/model/Sectors'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('SectorsView', () => { 7 | var fixtures; 8 | var model; 9 | var view; 10 | 11 | beforeEach(() => { 12 | model = new Sectors([]); 13 | view = new SectorsView({ 14 | collection: model 15 | }); 16 | document.body.innerHTML = '
'; 17 | fixtures = document.body.firstChild; 18 | fixtures.appendChild(view.render().el); 19 | }); 20 | 21 | afterEach(() => { 22 | view.collection.reset(); 23 | }); 24 | 25 | it('Collection is empty', () => { 26 | expect(view.el.innerHTML).toEqual(''); 27 | }); 28 | 29 | it('Add new sectors', () => { 30 | view.collection.add([{}, {}]); 31 | expect(view.el.children.length).toEqual(2); 32 | }); 33 | }); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /grapesjs/test/specs/test_utils.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | storageMock() { 3 | var db = {}; 4 | return { 5 | id: 'testStorage', 6 | store(data) { 7 | db = data; 8 | }, 9 | load(keys) { 10 | return db; 11 | }, 12 | getDb() { 13 | return db; 14 | } 15 | }; 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /grapesjs/test/specs/trait_manager/index.js: -------------------------------------------------------------------------------- 1 | const TraitManager = require('trait_manager'); 2 | const TraitsModel = require('./model/TraitsModel'); 3 | const TraitsView = require('./view/TraitsView'); 4 | 5 | describe('TraitManager', () => { 6 | describe('Main', () => { 7 | var obj; 8 | 9 | beforeEach(() => { 10 | obj = new TraitManager().init(); 11 | }); 12 | 13 | afterEach(() => { 14 | obj = null; 15 | }); 16 | }); 17 | 18 | TraitsModel.run(); 19 | TraitsView.run(); 20 | }); 21 | -------------------------------------------------------------------------------- /grapesjs/test/specs/trait_manager/model/TraitsModel.js: -------------------------------------------------------------------------------- 1 | const Trait = require('trait_manager/model/Trait'); 2 | const Component = require('dom_components/model/Component'); 3 | 4 | module.exports = { 5 | run() { 6 | describe('TraitModels', () => { 7 | var obj; 8 | var target; 9 | var modelName = 'title'; 10 | 11 | beforeEach(() => { 12 | target = new Component(); 13 | obj = new Trait({ 14 | name: modelName, 15 | target 16 | }); 17 | }); 18 | 19 | afterEach(() => { 20 | obj = null; 21 | }); 22 | 23 | it('Object exists', () => { 24 | expect(Trait).toExist(); 25 | }); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /grapesjs/test/specs/trait_manager/view/TraitsView.js: -------------------------------------------------------------------------------- 1 | const Trait = require('trait_manager/model/Trait'); 2 | const TraitView = require('trait_manager/view/TraitView'); 3 | const Component = require('dom_components/model/Component'); 4 | 5 | module.exports = { 6 | run() { 7 | describe('TraitView', () => { 8 | var obj; 9 | var model; 10 | var modelName = 'title'; 11 | var target; 12 | 13 | beforeEach(() => { 14 | target = new Component(); 15 | model = new Trait({ 16 | name: modelName, 17 | target 18 | }); 19 | obj = new TraitView({ 20 | model 21 | }); 22 | }); 23 | 24 | afterEach(() => { 25 | obj = null; 26 | model = null; 27 | target = null; 28 | }); 29 | 30 | it('Object exists', () => { 31 | expect(Trait).toExist(); 32 | }); 33 | 34 | it('Target has no attributes on init', () => { 35 | expect(target.get('attributes')).toEqual({}); 36 | }); 37 | 38 | it('On update of the value updates the target attributes', () => { 39 | model.set('value', 'test'); 40 | var eq = {}; 41 | eq[modelName] = 'test'; 42 | expect(target.get('attributes')).toEqual(eq); 43 | }); 44 | 45 | it('Updates on different models do not alter other targets', () => { 46 | var target1 = new Component(); 47 | var target2 = new Component(); 48 | var model1 = new Trait({ 49 | name: modelName, 50 | target: target1 51 | }); 52 | var model2 = new Trait({ 53 | name: modelName, 54 | target: target2 55 | }); 56 | var obj1 = new TraitView({ model: model1 }); 57 | var obj2 = new TraitView({ model: model2 }); 58 | 59 | model1.set('value', 'test1'); 60 | model2.set('value', 'test2'); 61 | var eq1 = {}; 62 | eq1[modelName] = 'test1'; 63 | var eq2 = {}; 64 | eq2[modelName] = 'test2'; 65 | expect(target1.get('attributes')).toEqual(eq1); 66 | expect(target2.get('attributes')).toEqual(eq2); 67 | }); 68 | }); 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /grapesjs/test/specs/utils/main.js: -------------------------------------------------------------------------------- 1 | define((require, exports, module) => { 2 | 'use strict'; 3 | var Utils = require('Utils'); 4 | var Sorter = require('undefined'); 5 | 6 | describe('Utils', () => { 7 | Sorter.run(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /grapesjs/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | const pkg = require('./package.json'); 3 | const webpack = require('webpack'); 4 | const fs = require('fs'); 5 | let plugins = []; 6 | 7 | module.exports = env => { 8 | 9 | const output = { 10 | filename: './dist/grapes.min.js', 11 | library: 'grapesjs', 12 | libraryTarget: 'umd', 13 | }; 14 | 15 | if (env == 'prod') { 16 | plugins = [ 17 | new webpack.optimize.ModuleConcatenationPlugin(), 18 | new webpack.optimize.UglifyJsPlugin({ minimize:true, compressor: {warnings:false}}), 19 | new webpack.BannerPlugin(`${pkg.name} - ${pkg.version}`), 20 | ]; 21 | } else if (env == 'dev') { 22 | output.filename = './dist/grapes.js'; 23 | } else { 24 | const index = 'index.html'; 25 | const indexDev = `_${index}`; 26 | const template = fs.existsSync(indexDev) ? indexDev : index; 27 | plugins.push(new HtmlWebpackPlugin({ template, inject: false })); 28 | } 29 | 30 | plugins.push(new webpack.ProvidePlugin({ 31 | _: 'underscore', 32 | Backbone: 'backbone' 33 | })); 34 | 35 | return { 36 | entry: './src', 37 | output: output, 38 | plugins: plugins, 39 | module: { 40 | loaders: [{ 41 | test: /\/index\.js$/, 42 | loader: 'string-replace-loader', 43 | query: { 44 | search: '<# VERSION #>', 45 | replace: pkg.version 46 | } 47 | },{ 48 | test: /\.js$/, 49 | loader: 'babel-loader', 50 | include: /src/ 51 | }], 52 | }, 53 | resolve: { 54 | modules: ['src', 'node_modules'], 55 | alias: { 56 | jquery: 'cash-dom' 57 | } 58 | } 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 34 | 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grapesjs-mavo", 3 | "version": "0.1.97", 4 | "description": "Mavo Create", 5 | "main": "dist/grapesjs-mavo.min.js", 6 | "scripts": { 7 | "lint": "eslint src", 8 | "v:patch": "npm version --no-git-tag-version patch", 9 | "build": "npm run v:patch && webpack --env.production && npm run build:css", 10 | "start": "webpack-dev-server --open --progress --colors & npm run build:css -- -w", 11 | "build:css": "node-sass src/style/main.scss dist/grapesjs-mavo.min.css --output-style compressed" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "" 16 | }, 17 | "keywords": [ 18 | "grapesjs", 19 | "plugin", 20 | "mavo", 21 | "wysiwyg" 22 | ], 23 | "author": "Francesca Cicileo", 24 | "license": "BSD-3-Clause", 25 | "babel": { 26 | "presets": [ 27 | "env" 28 | ], 29 | "plugins": [ 30 | "transform-object-rest-spread" 31 | ] 32 | }, 33 | "peerDependencies": { 34 | "grapesjs": "0.x" 35 | }, 36 | "devDependencies": { 37 | "babel-core": "^6.26.0", 38 | "babel-loader": "^7.1.4", 39 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 40 | "babel-preset-env": "^1.6.1", 41 | "eslint": "^4.19.1", 42 | "html-webpack-plugin": "^2.30.1", 43 | "node-sass": "^4.8.3", 44 | "webpack": "^3.11.0", 45 | "webpack-dev-server": "^2.11.2" 46 | }, 47 | "dependencies": { 48 | "grapesjs-aviary": "^0.1.2", 49 | "grapesjs-component-countdown": "^0.1.2", 50 | "grapesjs-navbar": "^0.1.5", 51 | "grapesjs-plugin-export": "^0.1.5", 52 | "grapesjs-plugin-filestack": "^0.1.1", 53 | "juice": "^4.1.1" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/commands/index.js: -------------------------------------------------------------------------------- 1 | import openImport from './openImport'; 2 | import { 3 | cmdImport, 4 | cmdDeviceDesktop, 5 | cmdDeviceTablet, 6 | cmdDeviceMobile, 7 | cmdClear, 8 | cmdExport 9 | } from './../consts'; 10 | 11 | export default (editor, config) => { 12 | const cm = editor.Commands; 13 | const txtConfirm = config.textCleanCanvas; 14 | const juice = require('juice'); 15 | 16 | cm.add(cmdImport, openImport(editor, config)); 17 | cm.add(cmdDeviceDesktop, e => e.setDevice('Desktop')); 18 | cm.add(cmdDeviceTablet, e => e.setDevice('Tablet')); 19 | cm.add(cmdDeviceMobile, e => e.setDevice('Mobile portrait')); 20 | cm.add(cmdClear, e => confirm(txtConfirm) && e.runCommand('core:canvas-clear')); 21 | cm.add(cmdExport, { 22 | run(editor) { 23 | const tmpl = editor.getHtml() + ``; 24 | return juice(tmpl); 25 | } 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /src/commands/openImport.js: -------------------------------------------------------------------------------- 1 | export default (editor, config) => { 2 | const pfx = editor.getConfig('stylePrefix'); 3 | const modal = editor.Modal; 4 | const codeViewer = editor.CodeManager.getViewer('CodeMirror').clone(); 5 | const container = document.createElement('div'); 6 | const importLabel = config.modalImportLabel; 7 | const importCnt = config.modalImportContent; 8 | let viewerEditor = codeViewer.editor; 9 | 10 | // Init import button 11 | const btnImp = document.createElement('button'); 12 | btnImp.type = 'button'; 13 | btnImp.innerHTML = config.modalImportButton; 14 | btnImp.className = `${pfx}btn-prim ${pfx}btn-import`; 15 | btnImp.onclick = e => { 16 | editor.setComponents(viewerEditor.getValue().trim()); 17 | modal.close(); 18 | }; 19 | 20 | // Init code viewer 21 | codeViewer.set({ ...{ 22 | codeName: 'htmlmixed', 23 | theme: 'hopscotch', 24 | readOnly: 0 25 | }, ...config.importViewerOptions}); 26 | 27 | return { 28 | run(editor) { 29 | if (!viewerEditor) { 30 | const txtarea = document.createElement('textarea'); 31 | 32 | if (importLabel) { 33 | const labelEl = document.createElement('div'); 34 | labelEl.className = `${pfx}import-label`; 35 | labelEl.innerHTML = importLabel; 36 | container.appendChild(labelEl); 37 | } 38 | 39 | container.appendChild(txtarea); 40 | container.appendChild(btnImp); 41 | codeViewer.init(txtarea); 42 | viewerEditor = codeViewer.editor; 43 | } 44 | 45 | modal.setTitle(config.modalImportTitle); 46 | modal.setContent(container); 47 | const cnt = typeof importCnt == 'function' ? importCnt(editor) : importCnt; 48 | codeViewer.setContent(cnt || ''); 49 | modal.open(); 50 | viewerEditor.refresh(); 51 | }, 52 | 53 | stop() { 54 | modal.close(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/consts.js: -------------------------------------------------------------------------------- 1 | export const 2 | cmdImport = 'gjs-open-import-webpage', 3 | cmdDeviceDesktop = 'set-device-desktop', 4 | cmdDeviceTablet = 'set-device-tablet', 5 | cmdDeviceMobile = 'set-device-mobile', 6 | cmdClear = 'canvas-clear', 7 | cmdExport = 'get-inlined-html'; 8 | -------------------------------------------------------------------------------- /src/style/_variables.scss: -------------------------------------------------------------------------------- 1 | /* Class names prefixes */ 2 | $prefix: 'gjs-' !default; 3 | 4 | /* Colors / Theme */ 5 | $primaryColor: #463a3c; 6 | $secondaryColor: #b9a5a6; 7 | $tertiaryColor: #804f7b; 8 | $quaternaryColor: #d97aa6; 9 | -------------------------------------------------------------------------------- /src/style/main.scss: -------------------------------------------------------------------------------- 1 | @import "variables.scss"; 2 | 3 | .#{$prefix} { 4 | @each $cnum, $ccol in (one, $primaryColor), (two, $secondaryColor), (three, $tertiaryColor), (four, $quaternaryColor) { 5 | &#{$cnum} { 6 | &-bg { 7 | background-color: $ccol; 8 | } 9 | 10 | &-color { 11 | color: $ccol; 12 | 13 | &-h:hover { 14 | color: $ccol; 15 | } 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/styles/index.js: -------------------------------------------------------------------------------- 1 | export default (editor, config) => { 2 | const sm = editor.StyleManager; 3 | const csm = config.customStyleManager; 4 | 5 | sm.getSectors().reset(csm && csm.length ? csm : [{ 6 | name: config.textGeneral, 7 | open: false, 8 | buildProps: ['float', 'display', 'position', 'top', 'right', 'left', 'bottom'], 9 | },{ 10 | name: config.textLayout, 11 | open: false, 12 | buildProps: ['width', 'height', 'max-width', 'min-height', 'margin', 'padding'], 13 | },{ 14 | name: config.textTypography, 15 | open: false, 16 | buildProps: ['font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', 'text-align', 'text-shadow'], 17 | properties: [{ 18 | property: 'text-align', 19 | list: [ 20 | { value: 'left', className: 'fa fa-align-left' }, 21 | { value: 'center', className: 'fa fa-align-center' }, 22 | { value: 'right', className: 'fa fa-align-right' }, 23 | { value: 'justify', className: 'fa fa-align-justify' }, 24 | ], 25 | }] 26 | },{ 27 | name: config.textDecorations, 28 | open: false, 29 | buildProps: ['border-radius-c', 'background-color', 'border-radius', 'border', 'box-shadow', 'background'], 30 | },{ 31 | name: config.textExtra, 32 | open: false, 33 | buildProps: ['transition', 'perspective', 'transform'], 34 | }]); 35 | } 36 | -------------------------------------------------------------------------------- /src/traits/index.js: -------------------------------------------------------------------------------- 1 | export default (editor, config = {}) => { 2 | const trm = editor.TraitManager; 3 | const textTrat = trm.getType('text'); 4 | 5 | trm.addType('content', { 6 | events:{ 7 | 'keyup': 'onChange', 8 | }, 9 | 10 | onValueChange: function () { 11 | var md = this.model; 12 | var target = md.target; 13 | target.set('content', md.get('value')); 14 | }, 15 | 16 | getInputEl: function() { 17 | if(!this.inputEl) { 18 | this.inputEl = textTrat.prototype.getInputEl.bind(this)(); 19 | this.inputEl.value = this.target.get('content'); 20 | } 21 | return this.inputEl; 22 | } 23 | }); 24 | 25 | 26 | trm.addType('select-options', { 27 | events:{ 28 | 'keyup': 'onChange', 29 | }, 30 | 31 | onValueChange: function () { 32 | var optionsStr = this.model.get('value').trim(); 33 | var options = optionsStr.split('\n'); 34 | var optComps = []; 35 | 36 | for (var i = 0; i < options.length; i++) { 37 | var optionStr = options[i]; 38 | var option = optionStr.split('::'); 39 | var opt = { 40 | tagName: 'option', 41 | attributes: {} 42 | }; 43 | if(option[1]) { 44 | opt.content = option[1]; 45 | opt.attributes.value = option[0]; 46 | } else { 47 | opt.content = option[0]; 48 | opt.attributes.value = option[0]; 49 | } 50 | optComps.push(opt); 51 | } 52 | 53 | var comps = this.target.get('components'); 54 | comps.reset(optComps); 55 | this.target.view.render(); 56 | }, 57 | 58 | getInputEl: function() { 59 | if (!this.$input) { 60 | var md = this.model; 61 | var trg = this.target; 62 | var name = md.get('name'); 63 | var optionsStr = ''; 64 | var opts = {placeholder: ''}; 65 | var options = trg.get('components'); 66 | 67 | for (var i = 0; i < options.length; i++) { 68 | var option = options.models[i]; 69 | var optAttr = option.get('attributes'); 70 | var optValue = optAttr.value || ''; 71 | optionsStr += `${optValue}::${option.get('content')}\n`; 72 | } 73 | 74 | this.$input = document.createElement('textarea'); 75 | this.$input.value = optionsStr; 76 | } 77 | return this.$input; 78 | }, 79 | }); 80 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | const pkg = require('./package.json'); 3 | const webpack = require('webpack'); 4 | const fs = require('fs'); 5 | const name = pkg.name; 6 | let plugins = []; 7 | 8 | module.exports = (env = {}) => { 9 | if (env.production) { 10 | plugins = [ 11 | new webpack.optimize.UglifyJsPlugin({ minimize: true, compressor: { warnings: false }}), 12 | new webpack.BannerPlugin(`${name} - ${pkg.version}`), 13 | ] 14 | } else { 15 | const index = 'index.html'; 16 | const indexDev = '_' + index; 17 | plugins.push(new HtmlWebpackPlugin({ 18 | template: fs.existsSync(indexDev) ? indexDev : index 19 | })); 20 | } 21 | 22 | return { 23 | entry: './src', 24 | output: { 25 | filename: `./dist/${name}.min.js`, 26 | library: name, 27 | libraryTarget: 'umd', 28 | }, 29 | module: { 30 | loaders: [{ 31 | test: /\.js$/, 32 | loader: 'babel-loader', 33 | include: /src/, 34 | }], 35 | }, 36 | externals: {'grapesjs': 'grapesjs'}, 37 | plugins: plugins, 38 | }; 39 | } 40 | --------------------------------------------------------------------------------