Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trait refactor #5562

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ed57e2d
Fix commit error
xQwexx Dec 13, 2023
e7e1a1b
Update rest of lint
xQwexx Dec 13, 2023
90c9930
Pages view v1
xQwexx Dec 13, 2023
3ca734b
Create trait
xQwexx Dec 13, 2023
d1a1756
Fix some stuff
xQwexx Dec 13, 2023
9f5d9a8
Add number trait
xQwexx Dec 14, 2023
c287790
Add the rest of the viewes
xQwexx Dec 14, 2023
83bcf5f
Add Factory
xQwexx Dec 15, 2023
e66f59f
Wire New Trait impl in the editor
xQwexx Dec 16, 2023
ccbaaf0
Add trait list
xQwexx Dec 18, 2023
26a963f
WIP traits refactor
xQwexx Dec 20, 2023
90b8cdd
WIP FunctionView
xQwexx Dec 27, 2023
6cc8a27
Upgrade codemirror to version 6
xQwexx Dec 27, 2023
f617381
Dependency fix build dist
xQwexx Dec 28, 2023
c8b8590
Remove original traits
xQwexx Dec 28, 2023
b0a3725
WIP TraitList
xQwexx Dec 28, 2023
e0cf69b
WIP TraitFunction
xQwexx Dec 28, 2023
2e5eb8d
Fix function list bug
xQwexx Dec 28, 2023
643f073
WIP
xQwexx Jan 4, 2024
6bfd5f5
WIP
xQwexx Jan 9, 2024
f221c11
WIP big work
xQwexx Feb 26, 2024
9f424d6
Move out Script generation logic from the Component
xQwexx Feb 26, 2024
ab5b3ee
small fixes
xQwexx Feb 27, 2024
38d5abc
Fix type
xQwexx Feb 27, 2024
6dee738
Fix tests
xQwexx Feb 27, 2024
5dd9936
small fix
xQwexx Feb 27, 2024
70881a6
Merge script string generators
xQwexx Feb 27, 2024
118c37c
Add slot signal script interface
xQwexx Feb 28, 2024
e1b4dd6
Merge branch 'script-module' into dev
xQwexx Mar 6, 2024
7c53e86
Fix trait panel class
xQwexx Mar 6, 2024
30cb072
Savepoint before switching js events
xQwexx Mar 8, 2024
982fb71
test signal slot
xQwexx Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dist/css/grapes.min.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/grapes.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/grapes.min.js.map

Large diffs are not rendered by default.

110,292 changes: 69,558 additions & 40,734 deletions dist/grapes.mjs

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion dist/grapes.mjs.map

Large diffs are not rendered by default.

2,584 changes: 1,445 additions & 1,139 deletions dist/index.d.ts

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1 class="welcome">Welcome to</h1>
border-radius: 3px;
padding: 30px 20px;
margin: 150px auto 0px;
background-color: #d983a6;
background-color: #b2b2b2;
box-shadow: 0px 3px 10px 0px rgba(0,0,0,0.25);
color:rgba(255,255,255,0.75);
font: caption;
Expand Down Expand Up @@ -86,6 +86,9 @@ <h1 class="welcome">Welcome to</h1>
height: '100%',
fromElement: true,
storageManager: { autoload: 0 },
canvas: {
scripts: [{src:'https://code.jquery.com/jquery-3.7.1.min.js', integrity:"sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=", crossorigin:"anonymous"}],
},
styleManager : {
sectors: [{
name: 'General',
Expand Down Expand Up @@ -122,5 +125,6 @@ <h1 class="welcome">Welcome to</h1>
content: `<div style="padding-top:50px; padding-bottom:50px; text-align:center">Test block</div>`
})
</script>
<script src ='https://code.jquery.com/jquery-3.7.1.min.js', integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=", crossorigin="anonymous"></script>
</body>
</html>
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "grapesjs",
"description": "Free and Open Source Web Builder Framework",
"version": "0.21.8",
"version": "0.21.11",
"author": "Artur Arseniev",
"license": "BSD-3-Clause",
"homepage": "http://grapesjs.com",
Expand Down Expand Up @@ -31,27 +31,29 @@
"url": "https://github.com/GrapesJS/grapesjs.git"
},
"dependencies": {
"@codemirror/theme-one-dark": "^6.1.2",
"@qwex/codemirror-beautify": "^0.0.3",
"@types/backbone": "^1.4.15",
"backbone": "1.4.1",
"backbone-undo": "^0.2.5",
"codemirror": "^5.63.0",
"codemirror-formatting": "^1.0.0",
"codemirror": "^6.0.1",
"codemirror-readonly-ranges": "^0.1.0-alpha.2",
"promise-polyfill": "^8.1.3",
"underscore": "^1.13.1"
},
"devDependencies": {
"@babel/cli": "^7.15.7",
"@babel/preset-typescript": "^7.16.7",
"@babel/preset-typescript": "^7.23.3",
"@types/jest": "^28.1.1",
"@typescript-eslint/parser": "^5.22.0",
"@typescript-eslint/parser": "^6.14.0",
"@vuepress/plugin-google-analytics": "^1.8.2",
"documentation": "^13.2.5",
"eslint": "^8.12.0",
"eslint": "^8.55.0",
"grapesjs-cli": "^4.1.3",
"html-entities": "^1.4.0",
"husky": "^2.7.0",
"jest": "^24.9.0",
"lint-staged": "^8.2.1",
"lint-staged": "^15.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.4.1",
"sass": "^1.42.1",
Expand Down
45 changes: 23 additions & 22 deletions src/canvas/view/CanvasView.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { bindAll, isNumber } from 'underscore';
import { bindAll, isArray, isNumber, isObject } from 'underscore';
import { ModuleView } from '../../abstract';
import { BoxRect, Coordinates, CoordinatesTypes, ElementRect } from '../../common';
import Component from '../../dom_components/model/Component';
Expand All @@ -19,6 +19,7 @@ import Frame from '../model/Frame';
import { GetBoxRectOptions, ToWorldOption } from '../types';
import FrameView from './FrameView';
import FramesView from './FramesView';
import ScriptSubComponent from '../../dom_components/model/modules/ScriptSubComponent';

export interface MarginPaddingOffsets {
marginTop?: number;
Expand Down Expand Up @@ -566,37 +567,37 @@ export default class CanvasView extends ModuleView<Canvas> {
* @param {ModuleView} view Component's View
* @private
*/
//TODO change type after the ComponentView was updated to ts
updateScript(view: any) {
updateScript(view: ComponentView) {
const model = view.model;
const id = model.getId();

console.log(
'//////////////////////////////////////////////////////////////////\n/////////////// updateScript////////////////'
);
if (!view.scriptContainer) {
view.scriptContainer = createEl('div', { 'data-id': id });
const jsEl = this.getJsContainer();
jsEl?.appendChild(view.scriptContainer);
}

view.el.id = id;
view.scriptContainer.innerHTML = '';
// In editor, I make use of setTimeout as during the append process of elements
// those will not be available immediately, therefore 'item' variable
const script = document.createElement('script');
const scriptFn = model.getScriptString();
const scriptFnStr = model.get('script-props') ? scriptFn : `function(){\n${scriptFn}\n;}`;
const scriptProps = JSON.stringify(model.__getScriptProps());
script.innerHTML = `
const scriptComponent = model.scriptSubComp;
if (scriptComponent) {
view.el.id = id;
view.scriptContainer.innerHTML = '';
// In editor, I make use of setTimeout as during the append process of elements
// those will not be available immediately, therefore 'item' variable
const script = document.createElement('script');
console.log(ScriptSubComponent.renderJs(scriptComponent));
script.innerHTML = `
setTimeout(function() {
var item = document.getElementById('${id}');
if (!item) return;
(${scriptFnStr}.bind(item))(${scriptProps})
${ScriptSubComponent.renderJs(scriptComponent)}
}, 1);`;
// #873
// Adding setTimeout will make js components work on init of the editor
setTimeout(() => {
const scr = view.scriptContainer;
scr?.appendChild(script);
}, 0);
// #873
// Adding setTimeout will make js components work on init of the editor
setTimeout(() => {
const scr = view.scriptContainer;
scr?.appendChild(script);
}, 0);
}
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/canvas/view/FrameView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,13 @@ export default class FrameView extends ModuleView<Frame, HTMLIFrameElement> {

if (hasDnd(em)) {
this.droppable = new Droppable(em, this.wrapper?.el);
root?.on(
'rerender',
wrp => {
this.droppable = new Droppable(em, wrp?.el);
},
this
);
}

this.loaded = true;
Expand Down
150 changes: 102 additions & 48 deletions src/code_manager/model/CodeMirrorEditor.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { bindAll } from 'underscore';
import { Model } from '../../common';
import { hasWin } from '../../utils/mixins';

let CodeMirror: any;

if (hasWin()) {
CodeMirror = require('codemirror/lib/codemirror');
require('codemirror/mode/htmlmixed/htmlmixed');
require('codemirror/mode/css/css');
require('codemirror-formatting');
}
import { EditorState, Extension, Compartment } from '@codemirror/state';
import { EditorViewConfig, lineNumbers, lineNumberMarkers, gutterLineClass, ViewUpdate } from '@codemirror/view';
import readOnlyRangesExtension from 'codemirror-readonly-ranges';
import { EditorView, basicSetup } from 'codemirror';
import { LanguageSupport, syntaxHighlighting } from '@codemirror/language';
import { oneDarkTheme, oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
import { autoFormaAll } from '@qwex/codemirror-beautify';
import { javascript } from '@codemirror/lang-javascript';
import { html } from '@codemirror/lang-html';
import { css } from '@codemirror/lang-css';

export default class CodeMirrorEditor extends Model {
editor?: any;
editor?: EditorView;
element?: HTMLElement;
private readOnlyCompartment = new Compartment();
private lineNumbersCompartment = new Compartment();

defaults() {
return {
Expand All @@ -24,29 +26,90 @@ export default class CodeMirrorEditor extends Model {
readOnly: true,
lineNumbers: true,
autoFormat: true,
readOnlyRanges: (targetState: EditorState) => {
return [] as Array<{ from: number | undefined; to: number | undefined }>;
},
};
}

init(el: HTMLElement) {
bindAll(this, 'onChange');
this.editor = CodeMirror.fromTextArea(el, {
dragDrop: false,
lineWrapping: true,
mode: this.get('codeName'),
get readonly(): boolean {
return this.get('readOnly');
}

get readOnlyRanges() {
return this.get('readOnlyRanges');
}

private editorFromTextArea(textarea: HTMLTextAreaElement, config: EditorViewConfig) {
let view = new EditorView({ doc: textarea.value, ...config });
textarea.parentNode?.insertBefore(view.dom, textarea);
textarea.style.display = 'none';
if (textarea.form)
textarea.form.addEventListener('submit', () => {
textarea.value = view.state.doc.toString();
});
return view;
}

private getCodeLanguage(name: string) {
switch (name) {
case 'htmlmixed':
return html();
case 'css':
return css();
case 'js':
return javascript();
default:
return undefined;
}
}

private setReadonlyState(readOnly: boolean) {
const { editor, readOnlyCompartment } = this;
if (editor) {
const readonlyState = editor.state.update({
effects: [readOnlyCompartment.reconfigure(EditorState.readOnly.of(readOnly))],
});
editor.update([readonlyState]);
}
}

init(el: HTMLTextAreaElement) {
// bindAll(this, 'onChange');
const languageState = this.getCodeLanguage(this.get('codeName'));

let extensions: Extension[] = [];
extensions.push(basicSetup);
extensions.push(oneDarkTheme);
extensions.push(this.lineNumbersCompartment.of(lineNumbers()));
extensions.push(syntaxHighlighting(oneDarkHighlightStyle));
languageState && extensions.push(languageState);
extensions.push(this.readOnlyCompartment.of(EditorState.readOnly.of(this.readonly)));
extensions.push(readOnlyRangesExtension(this.readOnlyRanges));
extensions.push(
EditorView.updateListener.of((v: ViewUpdate) => {
if (v.docChanged) {
// Document changed
this.trigger('update', this);
}
})
);
const state = EditorState.create({
doc: el.value,
extensions,
});

this.editor = this.editorFromTextArea(el, {
state,
...this.attributes,
});
this.element = el;
this.editor.on('change', this.onChange);

return this;
}

onChange() {
this.trigger('update', this);
}

getEditor() {
return this.editor;
return this.editor!;
}

/**
Expand All @@ -69,15 +132,6 @@ export default class CodeMirrorEditor extends Model {
return this;
}

/**
* Refresh the viewer
* @return {self}
*/
refresh() {
this.getEditor().refresh();
return this;
}

/**
* Focus the viewer
* @return {self}
Expand All @@ -89,28 +143,28 @@ export default class CodeMirrorEditor extends Model {

getContent() {
const ed = this.getEditor();
return ed && ed.getValue();
return ed && ed.state.doc;
}

/** @inheritdoc */
setContent(value: string, opts: any = {}) {
const { editor } = this;
if (!editor) return;
editor.setValue(value);
const autoFormat = this.get('autoFormat');
const canAutoFormat =
editor.autoFormatRange &&
(autoFormat === true || (Array.isArray(autoFormat) && autoFormat.includes(this.get('codeName'))));

if (canAutoFormat) {
CodeMirror.commands.selectAll(editor);
editor.autoFormatRange(editor.getCursor(true), editor.getCursor(false));
CodeMirror.commands.goDocStart(editor);
const { readonly } = this;
if (this.editor) {
this.setReadonlyState(false);
const state = this.editor.state;
const update = state.update({ changes: { from: 0, to: state.doc.length, insert: value } });
this.editor.update([update]);
const autoFormat = this.get('autoFormat');
const canAutoFormat =
autoFormat === true || (Array.isArray(autoFormat) && autoFormat.includes(this.get('codeName')));

if (canAutoFormat) {
autoFormaAll(this.editor);
}
this.setReadonlyState(readonly);
}

!opts.noRefresh && setTimeout(() => this.refresh());
}
}

// @ts-ignore
CodeMirrorEditor.prototype.CodeMirror = CodeMirror;
CodeMirrorEditor.prototype.CodeMirror = EditorView;
Loading