feat(Code Editor): Ace Editor for Code fieldtypes
- Better editing experience with syntax highlighting and auto-completion - Support HTML, Javascript and CSS language modes via the Options field
This commit is contained in:
parent
6beac087db
commit
c88f05d711
4 changed files with 85 additions and 5 deletions
|
|
@ -1,8 +1,78 @@
|
|||
frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({
|
||||
make_input: function() {
|
||||
this._super();
|
||||
$(this.input_area).find("textarea")
|
||||
.allowTabs()
|
||||
.addClass('control-code');
|
||||
make_input() {
|
||||
if (this.editor) return;
|
||||
this.load_lib().then(() => this.make_ace_editor());
|
||||
},
|
||||
|
||||
make_ace_editor() {
|
||||
const ace_editor_target = $('<div class="ace-editor-target"></div>')
|
||||
.appendTo(this.input_area);
|
||||
|
||||
// styling
|
||||
ace_editor_target.addClass('border rounded');
|
||||
ace_editor_target.css('height', 300);
|
||||
|
||||
// initialize
|
||||
this.editor = ace.edit(ace_editor_target.get(0));
|
||||
this.editor.setTheme('ace/theme/tomorrow');
|
||||
this.set_language();
|
||||
|
||||
// events
|
||||
this.editor.session.on('change', frappe.utils.debounce((delta) => {
|
||||
const input_value = this.get_input_value();
|
||||
this.parse_validate_and_set_in_model(input_value);
|
||||
}, 300));
|
||||
},
|
||||
|
||||
set_language() {
|
||||
const language_map = {
|
||||
'Javascript': 'ace/mode/javascript',
|
||||
'HTML': 'ace/mode/html',
|
||||
'CSS': 'ace/mode/css'
|
||||
}
|
||||
const language = this.df.options;
|
||||
|
||||
const valid_languages = Object.keys(language_map);
|
||||
if (!valid_languages.includes(language)) {
|
||||
console.warn(`Invalid language option provided for field "${this.df.label}". Valid options are ${valid_languages.join(', ')}.`);
|
||||
}
|
||||
|
||||
const ace_language_mode = language_map[language] || '';
|
||||
this.editor.session.setMode(ace_language_mode);
|
||||
},
|
||||
|
||||
parse(value) {
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
set_formatted_input(value) {
|
||||
this.library_loaded.then(() => {
|
||||
if (value === this.get_input_value()) return;
|
||||
this.editor.session.setValue(value);
|
||||
});
|
||||
},
|
||||
|
||||
get_input_value() {
|
||||
return this.editor ? this.editor.session.getValue() : '';
|
||||
},
|
||||
|
||||
load_lib() {
|
||||
if (frappe.boot.developer_mode) {
|
||||
this.root_lib_path = '/assets/frappe/js/lib/ace-builds/src-noconflict/';
|
||||
} else {
|
||||
this.root_lib_path = '/assets/frappe/js/lib/ace-builds/src-min-noconflict/';
|
||||
}
|
||||
|
||||
this.library_loaded = new Promise(resolve => {
|
||||
frappe.require(this.root_lib_path + 'ace.js', () => {
|
||||
window.ace.config.set('basePath', this.root_lib_path);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return this.library_loaded;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ a.badge-hover& {
|
|||
border: 1px solid @border-color;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.close-inline {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
},
|
||||
"homepage": "https://frappe.io",
|
||||
"dependencies": {
|
||||
"ace-builds": "^1.4.1",
|
||||
"awesomplete": "^1.1.2",
|
||||
"cookie": "^0.3.1",
|
||||
"express": "^4.16.2",
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ accepts@~1.3.4:
|
|||
mime-types "~2.1.16"
|
||||
negotiator "0.6.1"
|
||||
|
||||
ace-builds@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.1.tgz#a66e33bcd519918ee99bc54cac5d7399a83c8ff2"
|
||||
integrity sha512-ulsfTOi/oAXBIt9hYlK4asyFZYsFOOUAbwBZidbjWWJycRX4LtwIithMyndcnoQ4PavkZ0iGJ+c9nqHNiYbubA==
|
||||
|
||||
acorn-dynamic-import@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue