Merge pull request #19 from CodeFalling/better-jsx-like-event

Better jsx-like event binding
This commit is contained in:
dntzhang 2017-02-27 18:25:38 -06:00 committed by GitHub
commit 22c25cc47f
6 changed files with 121 additions and 13 deletions

26
dist/omi.js vendored
View File

@ -1636,6 +1636,25 @@ return /******/ (function(modules) { // webpackBootstrap
Object.defineProperty(exports, "__esModule", {
value: true
});
function exchange(str, a, b) {
return str.split(a).map(function (item) {
return item.replace(new RegExp(b, 'g'), a);
}).join(b);
}
function safeDoubleQuote(str) {
return JSON.stringify(str).replace(/(^"|"$)/g, '');
}
function safeSingleQuote(str) {
str = exchange(str, "'", '"');
return exchange(safeDoubleQuote(str), "'", '"');
}
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function scopedEvent(tpl, id) {
return tpl.replace(/<[\s\S]*?[^=]>/g, function (item) {
return item.replace(/on(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave|Abort|Blur|Cancel|CanPlay|CanPlayThrough|Change|Click|Close|ContextMenu|CueChange|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|Drop|DurationChange|Emptied|Ended|Error|Focus|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|LoadedData|LoadedMetadata|LoadStart|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Pause|Play|Playing|Progress|RateChange|Reset|Resize|Scroll|Seeked|Seeking|Select|Show|Stalled|Submit|Suspend|TimeUpdate|Toggle|VolumeChange|Waiting|AutoComplete|AutoCompleteError|BeforeCopy|BeforeCut|BeforePaste|Copy|Cut|Paste|Search|SelectStart|Wheel|WebkitFullScreenChange|WebkitFullScreenError|TouchStart|TouchMove|TouchEnd|TouchCancel|PointerDown|PointerUp|PointerCancel|PointerMove|PointerOver|PointerOut|PointerEnter|PointerLeave)=('|"|{)([\s\S]*)('|"|})/g, function (eventStr, eventName, open, str, close) {
@ -1644,8 +1663,11 @@ return /******/ (function(modules) { // webpackBootstrap
}
if (open === '{') {
// JSX-like event bind
var result = 'on' + eventName + '="new Function(\'event\', \'(' + str.replace(/'/g, '"') + ').bind(Omi.instances[' + id + '])(event)\')(event)"';
return result.replace(/\n/g, '');
var funcBody = '(' + str + ').bind(Omi.instances[' + id + '])(event)';
var result = 'on' + eventName + '="new Function(\'event\', \'' + escapeHtml(safeSingleQuote(funcBody)) + '\')(event)"';
return result.split('\n').map(function (line) {
return line.endsWith(';') ? line : line + ';';
}).join('');
} else {
if (!str.match(/.*?\(.*?\)/)) {
// if is not JSX-like event and is not a function call (func(xxx, ttt))

26
dist/omi.lite.js vendored
View File

@ -1019,6 +1019,25 @@ return /******/ (function(modules) { // webpackBootstrap
Object.defineProperty(exports, "__esModule", {
value: true
});
function exchange(str, a, b) {
return str.split(a).map(function (item) {
return item.replace(new RegExp(b, 'g'), a);
}).join(b);
}
function safeDoubleQuote(str) {
return JSON.stringify(str).replace(/(^"|"$)/g, '');
}
function safeSingleQuote(str) {
str = exchange(str, "'", '"');
return exchange(safeDoubleQuote(str), "'", '"');
}
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function scopedEvent(tpl, id) {
return tpl.replace(/<[\s\S]*?[^=]>/g, function (item) {
return item.replace(/on(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave|Abort|Blur|Cancel|CanPlay|CanPlayThrough|Change|Click|Close|ContextMenu|CueChange|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|Drop|DurationChange|Emptied|Ended|Error|Focus|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|LoadedData|LoadedMetadata|LoadStart|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Pause|Play|Playing|Progress|RateChange|Reset|Resize|Scroll|Seeked|Seeking|Select|Show|Stalled|Submit|Suspend|TimeUpdate|Toggle|VolumeChange|Waiting|AutoComplete|AutoCompleteError|BeforeCopy|BeforeCut|BeforePaste|Copy|Cut|Paste|Search|SelectStart|Wheel|WebkitFullScreenChange|WebkitFullScreenError|TouchStart|TouchMove|TouchEnd|TouchCancel|PointerDown|PointerUp|PointerCancel|PointerMove|PointerOver|PointerOut|PointerEnter|PointerLeave)=('|"|{)([\s\S]*)('|"|})/g, function (eventStr, eventName, open, str, close) {
@ -1027,8 +1046,11 @@ return /******/ (function(modules) { // webpackBootstrap
}
if (open === '{') {
// JSX-like event bind
var result = 'on' + eventName + '="new Function(\'event\', \'(' + str.replace(/'/g, '"') + ').bind(Omi.instances[' + id + '])(event)\')(event)"';
return result.replace(/\n/g, '');
var funcBody = '(' + str + ').bind(Omi.instances[' + id + '])(event)';
var result = 'on' + eventName + '="new Function(\'event\', \'' + escapeHtml(safeSingleQuote(funcBody)) + '\')(event)"';
return result.split('\n').map(function (line) {
return line.endsWith(';') ? line : line + ';';
}).join('');
} else {
if (!str.match(/.*?\(.*?\)/)) {
// if is not JSX-like event and is not a function call (func(xxx, ttt))

View File

@ -135,7 +135,7 @@
}, {
key: 'render',
value: function render() {
return '\n <div>\n {{{img}}}\n <h1 onclick={function(e){\n console.log(this);\n console.log(e);\n alert(e.type);\n }}>Hello, {{name}}!</h1>\n </div>\n \t\t';
return '\n <div>\n {{{img}}}\n <h1 onclick={function(e){\n console.log(this)\n console.log(e)\n console.log(\'test \\\' test "double quote"\')\n console.log("test \\"")\n }}>Hello, {{name}}!</h1>\n </div>\n \t\t';
}
}]);
@ -1727,6 +1727,25 @@
Object.defineProperty(exports, "__esModule", {
value: true
});
function exchange(str, a, b) {
return str.split(a).map(function (item) {
return item.replace(new RegExp(b, 'g'), a);
}).join(b);
}
function safeDoubleQuote(str) {
return JSON.stringify(str).replace(/(^"|"$)/g, '');
}
function safeSingleQuote(str) {
str = exchange(str, "'", '"');
return exchange(safeDoubleQuote(str), "'", '"');
}
function escapeHtml(unsafe) {
return unsafe.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}
function scopedEvent(tpl, id) {
return tpl.replace(/<[\s\S]*?[^=]>/g, function (item) {
return item.replace(/on(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave|Abort|Blur|Cancel|CanPlay|CanPlayThrough|Change|Click|Close|ContextMenu|CueChange|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|Drop|DurationChange|Emptied|Ended|Error|Focus|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|LoadedData|LoadedMetadata|LoadStart|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Pause|Play|Playing|Progress|RateChange|Reset|Resize|Scroll|Seeked|Seeking|Select|Show|Stalled|Submit|Suspend|TimeUpdate|Toggle|VolumeChange|Waiting|AutoComplete|AutoCompleteError|BeforeCopy|BeforeCut|BeforePaste|Copy|Cut|Paste|Search|SelectStart|Wheel|WebkitFullScreenChange|WebkitFullScreenError|TouchStart|TouchMove|TouchEnd|TouchCancel|PointerDown|PointerUp|PointerCancel|PointerMove|PointerOver|PointerOut|PointerEnter|PointerLeave)=('|"|{)([\s\S]*)('|"|})/g, function (eventStr, eventName, open, str, close) {
@ -1735,8 +1754,11 @@
}
if (open === '{') {
// JSX-like event bind
var result = 'on' + eventName + '="new Function(\'event\', \'(' + str.replace(/'/g, '"') + ').bind(Omi.instances[' + id + '])(event)\')(event)"';
return result.replace(/\n/g, '');
var funcBody = '(' + str + ').bind(Omi.instances[' + id + '])(event)';
var result = 'on' + eventName + '="new Function(\'event\', \'' + escapeHtml(safeSingleQuote(funcBody)) + '\')(event)"';
return result.split('\n').map(function (line) {
return line.endsWith(';') ? line : line + ';';
}).join('');
} else {
if (!str.match(/.*?\(.*?\)/)) {
// if is not JSX-like event and is not a function call (func(xxx, ttt))

View File

@ -20,9 +20,10 @@ class Hello extends Omi.Component {
<div>
{{{img}}}
<h1 onclick={function(e){
console.log(this);
console.log(e);
alert(e.type);
console.log(this)
console.log(e)
console.log('test \\' test "double quote"')
console.log("test \\"")
}}>Hello, {{name}}!</h1>
</div>
`;

View File

@ -1,3 +1,25 @@
function exchange(str, a, b) {
return str.split(a).map(function(item){return item.replace(new RegExp(b, 'g'), a)}).join(b);
}
function safeDoubleQuote(str) {
return JSON.stringify(str).replace(/(^"|"$)/g, '');
}
function safeSingleQuote(str) {
str = exchange(str, "'", '"');
return exchange(safeDoubleQuote(str), "'", '"');
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function scopedEvent(tpl,id) {
return tpl.replace(/<[\s\S]*?[^=]>/g, function (item) {
return item.replace(/on(abort|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|dblclick|drag|dragend|dragenter|dragleave|dragover|dragstart|drop|durationchange|emptied|ended|error|focus|input|invalid|keydown|keypress|keyup|load|loadeddata|loadedmetadata|loadstart|mousedown|mouseenter|mouseleave|mousemove|mouseout|mouseover|mouseup|mousewheel|pause|play|playing|progress|ratechange|reset|resize|scroll|seeked|seeking|select|show|stalled|submit|suspend|timeupdate|toggle|volumechange|waiting|autocomplete|autocompleteerror|beforecopy|beforecut|beforepaste|copy|cut|paste|search|selectstart|wheel|webkitfullscreenchange|webkitfullscreenerror|touchstart|touchmove|touchend|touchcancel|pointerdown|pointerup|pointercancel|pointermove|pointerover|pointerout|pointerenter|pointerleave|Abort|Blur|Cancel|CanPlay|CanPlayThrough|Change|Click|Close|ContextMenu|CueChange|DblClick|Drag|DragEnd|DragEnter|DragLeave|DragOver|DragStart|Drop|DurationChange|Emptied|Ended|Error|Focus|Input|Invalid|KeyDown|KeyPress|KeyUp|Load|LoadedData|LoadedMetadata|LoadStart|MouseDown|MouseEnter|MouseLeave|MouseMove|MouseOut|MouseOver|MouseUp|MouseWheel|Pause|Play|Playing|Progress|RateChange|Reset|Resize|Scroll|Seeked|Seeking|Select|Show|Stalled|Submit|Suspend|TimeUpdate|Toggle|VolumeChange|Waiting|AutoComplete|AutoCompleteError|BeforeCopy|BeforeCut|BeforePaste|Copy|Cut|Paste|Search|SelectStart|Wheel|WebkitFullScreenChange|WebkitFullScreenError|TouchStart|TouchMove|TouchEnd|TouchCancel|PointerDown|PointerUp|PointerCancel|PointerMove|PointerOver|PointerOut|PointerEnter|PointerLeave)=('|"|{)([\s\S]*)('|"|})/g, function (eventStr, eventName, open, str, close) {
@ -6,8 +28,11 @@ function scopedEvent(tpl,id) {
}
if (open === '{') {
// JSX-like event bind
const result = `on${eventName}="new Function('event', '(${str.replace(/'/g, '"')}).bind(Omi.instances[${id}])(event)')(event)"`;
return result.replace(/\n/g, '');
const funcBody = `(${str}).bind(Omi.instances[${id}])(event)`;
const result = `on${eventName}="new Function('event', '${escapeHtml(safeSingleQuote(funcBody))}')(event)"`;
return result.split('\n').map(function(line) {
return line.endsWith(';') ? line : line + ';';
}).join('');
} else {
if (!str.match(/.*?\(.*?\)/)) {
// if is not JSX-like event and is not a function call (func(xxx, ttt))

View File

@ -17,4 +17,20 @@ describe("scopedEvent2", function() {
expect(result).toBe("<div onclick='adfd'>sfsdf </div>");
});
});
});
describe("jsx-like event binding", function() {
var result = scopedEvent("<div onclick={function(e){console.log(this)}}>sfsdf </div>",1);
it("and so is a spec", function() {
expect(result).toBe(`<div onclick="new Function('event', '(function(e){console.log(this)}).bind(Omi.instances[1])(event)')(event)";>sfsdf </div>`);
});
});
describe("jsx-like event binding with quote", function() {
var result = scopedEvent('<div onclick={function(e){console.log("string with sigal quote \' and double quote \"")}}>sfsdf </div>',1);
it("and so is a spec", function() {
expect(result).toBe(`<div onclick="new Function('event', '(function(e){console.log(&quot;string with sigal quote \\&#039; and double quote &quot;&quot;)}).bind(Omi.instances[1])(event)')(event)";>sfsdf </div>`);
});
});