Skip to content
This repository has been archived by the owner on Nov 2, 2021. It is now read-only.

Commit

Permalink
Merge pull request #33 from fxos/bug1159454
Browse files Browse the repository at this point in the history
Bug 1159454 - [Customizer] Perform JavaScript code validation for 'Scrip...
  • Loading branch information
justindarc committed Apr 30, 2015
2 parents 44f6c97 + 1c80a8c commit e33dbf6
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 18 deletions.
3 changes: 2 additions & 1 deletion _custombuild
Expand Up @@ -64,7 +64,8 @@ var components = gulp.src([
APP_ROOT + 'components/gaia-list/gaia-list.js',
APP_ROOT + 'components/gaia-button/gaia-button.js',
APP_ROOT + 'components/gaia-switch/gaia-switch.js',
APP_ROOT + 'components/jszip/dist/jszip.js'
APP_ROOT + 'components/jszip/dist/jszip.js',
APP_ROOT + 'components/esprima/esprima.js'
])
.pipe(concat('components-concat.js'))

Expand Down
107 changes: 107 additions & 0 deletions app/js/elements/fxos-code-editor.js
@@ -0,0 +1,107 @@
(function(window) {
'use strict';

var proto = Object.create(HTMLElement.prototype);

var template =
`<style>
.container {
position: relative;
width: 100%;
height: 100%;
}
.line-numbers {
background: #6363ce;
color: #fff;
font-family: Consolas,Monaco,"Andale Mono",monospace;
font-size: 14px;
line-height: 1.2em;
position: absolute;
top: 0;
left: 0;
width: 32px;
height: 100%;
overflow: hidden;
}
textarea {
background: #000;
border: none;
color: #fff;
font-family: Consolas,Monaco,"Andale Mono",monospace;
font-size: 14px;
line-height: 1.2em;
position: absolute;
top: 0;
left: 32px;
width: calc(100% - 32px);
height: 100%;
margin: 0;
padding: 0;
-moz-user-select: text !important;
}
.line-numbers,
textarea {
font-family: Consolas,Monaco,"Andale Mono",monospace;
font-size: 14px;
line-height: 1.2em;
}
</style>
<div class="container">
<div class="line-numbers"></div>
<textarea wrap="off"></textarea>
</div>`;

proto.createdCallback = function() {
var value = this.innerHTML;

this.shadow = this.createShadowRoot();
this.shadow.innerHTML = template;

this.lineNumbers = this.shadow.querySelector('.line-numbers');

this.textarea = this.shadow.querySelector('textarea');
this.textarea.value = value;

this.textarea.addEventListener('keyup', () => {
this.dispatchEvent(new CustomEvent('change'));
updateLineNumbers(this);
});

this.textarea.addEventListener('scroll', () => {
this.lineNumbers.scrollTop = this.textarea.scrollTop;
});
};

Object.defineProperty(proto, 'value', {
get: function() {
return this.textarea.value;
},

set: function(value) {
this.textarea.value = value;
this.dispatchEvent(new CustomEvent('change'));
updateLineNumbers(this);
}
});

function updateLineNumbers(element) {
var html = '';

var lines = element.value.split('\n').length;
for (var i = 1; i <= lines; i++) {
html += '<div>' + i + '</div>';
}

element.lineNumbers.innerHTML = html;
element.lineNumbers.scrollTop = element.textarea.scrollTop;
}

try {
document.registerElement('fxos-code-editor', { prototype: proto });
} catch (e) {
if (e.name !== 'NotSupportedError') {
throw e;
}
}

})(window);
82 changes: 66 additions & 16 deletions app/js/views/edit.js
@@ -1,5 +1,6 @@
/* global View */

/* global esprima */
/* global html_beautify */

var editViewTemplate =
Expand Down Expand Up @@ -30,12 +31,6 @@ var editViewTemplate =
.tab-pane.active {
display: block;
}
textarea {
border: none;
font-family: Consolas,Monaco,"Andale Mono",monospace;
width: 100%;
height: 100%;
}
textarea,
input {
-moz-user-select: text !important;
Expand All @@ -50,6 +45,30 @@ var editViewTemplate =
background: #000;
color: #fff;
}
fxos-code-editor {
width: 100%;
height: 100%;
}
.errors {
background: #820000;
color: #fff;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 20px;
overflow: hidden;
z-index: 2;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.errors.active {
opacity: 1;
}
.errors.active ~ fxos-code-editor {
height: calc(100% - 20px);
}
</style>
<gaia-header>
<button data-action="cancel" data-icon="close"></button>
Expand All @@ -63,10 +82,11 @@ var editViewTemplate =
<a href="#">Properties</a>
</gaia-tabs>
<section class="tab-pane active" data-id="html">
<textarea></textarea>
<fxos-code-editor></fxos-code-editor>
</section>
<section class="tab-pane" data-id="script">
<textarea></textarea>
<div class="errors"></div>
<fxos-code-editor></fxos-code-editor>
</section>
<section class="tab-pane" data-id="attributes">
<gaia-property-inspector root-property="attributes" data-textarea="textarea"></gaia-property-inspector>
Expand All @@ -92,11 +112,13 @@ export default class EditView extends View {
this.header = this.$('gaia-header');
this.tabs = this.$('gaia-tabs');

this.htmlTextarea = this.$('section[data-id="html"] > textarea');
this.scriptTextarea = this.$('section[data-id="script"] > textarea');
this.htmlCodeEditor = this.$('section[data-id="html"] > fxos-code-editor');
this.scriptCodeEditor = this.$('section[data-id="script"] > fxos-code-editor');
this.attributeInspector = this.$('section[data-id="attributes"] > gaia-property-inspector');
this.propertyInspector = this.$('section[data-id="properties"] > gaia-property-inspector');

this.scriptErrors = this.$('section[data-id="script"] > .errors');

this.tabPanes = [].slice.apply(this.$$('.tab-pane'));

this.on('click', 'button[data-action="cancel"]', (evt) => {
Expand All @@ -117,12 +139,15 @@ export default class EditView extends View {
});
});

this.htmlTextarea.addEventListener('keyup', (evt) => {
this.controller.changes.innerHTML = this.htmlTextarea.value;
this.htmlCodeEditor.addEventListener('change', (evt) => {
this.controller.changes.innerHTML = this.htmlCodeEditor.value;
});

this.scriptTextarea.addEventListener('keyup', (evt) => {
this.controller.changes.script = this.scriptTextarea.value;
this.scriptCodeEditor.addEventListener('change', (evt) => {
this.controller.changes.script = this.scriptCodeEditor.value;

clearTimeout(this.validateScriptTimeout);
this.validateScriptTimeout = setTimeout(this.validateScript.bind(this), 1000);
});

this.on('save', 'gaia-property-inspector', (evt) => {
Expand Down Expand Up @@ -158,8 +183,8 @@ export default class EditView extends View {
indent_size: 2
});

this.htmlTextarea.value = html;
this.scriptTextarea.value =
this.htmlCodeEditor.value = html;
this.scriptCodeEditor.value =
`/**
* You can edit a script to be inserted
* in the generated add-on here.
Expand All @@ -178,4 +203,29 @@ export default class EditView extends View {
this.attributeInspector.set(clonedTarget);
this.propertyInspector.set(clonedTarget);
}

validateScript() {
var error;

try {
var syntax = esprima.parse(this.controller.changes.script);
if (syntax.errors && syntax.errors.length > 0) {
error = syntax.errors[0];
}
}

catch (e) {
error = e;
}

if (error) {
this.scriptErrors.textContent = error.message;
this.scriptErrors.classList.add('active');
}

else {
this.scriptErrors.textContent = '';
this.scriptErrors.classList.remove('active');
}
}
}
3 changes: 2 additions & 1 deletion bower.json
Expand Up @@ -25,7 +25,8 @@
"js-beautify": "~1.5.5",
"jszip": "~2.5.0",
"observe-shim": "~0.4.2",
"observe-utils": "~0.3.2"
"observe-utils": "~0.3.2",
"esprima": "~2.0.0"
},
"resolutions": {
"font-fit": "~0.3.0"
Expand Down

0 comments on commit e33dbf6

Please sign in to comment.