Merge pull request #8941 from Microsoft/controlFlowPropertyDeclarations
Create control flows for property declarations
This commit is contained in:
Коммит
9f087cb62a
|
@ -1142,6 +1142,8 @@ namespace ts {
|
|||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return ContainerFlags.IsControlFlowContainer;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return (<PropertyDeclaration>node).initializer ? ContainerFlags.IsControlFlowContainer : 0;
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ForStatement:
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
//// [controlFlowPropertyDeclarations.ts]
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
private output: string;
|
||||
private level: number;
|
||||
private _inPreTag: boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
|
||||
if (this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
styles = {};
|
||||
toJSXString = () => {
|
||||
for (var key in this.styles) {
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowPropertyDeclarations.js]
|
||||
// Repro from ##8913
|
||||
"use strict";
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) {
|
||||
throw new Error();
|
||||
}
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function (match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
var HTMLtoJSX = (function () {
|
||||
function HTMLtoJSX() {
|
||||
var _this = this;
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
this._visitText = function (node) {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
var text = '';
|
||||
if (_this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function (whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
}
|
||||
else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
_this.output += text;
|
||||
};
|
||||
}
|
||||
return HTMLtoJSX;
|
||||
}());
|
||||
exports.HTMLtoJSX = HTMLtoJSX;
|
||||
;
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
var StyleParser = (function () {
|
||||
function StyleParser() {
|
||||
var _this = this;
|
||||
this.styles = {};
|
||||
this.toJSXString = function () {
|
||||
for (var key in _this.styles) {
|
||||
if (!_this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return StyleParser;
|
||||
}());
|
||||
exports.StyleParser = StyleParser;
|
|
@ -0,0 +1,288 @@
|
|||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : Symbol(mapFrom, Decl(controlFlowPropertyDeclarations.ts, 13, 5))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>propname.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : Symbol(repeatString, Decl(controlFlowPropertyDeclarations.ts, 14, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times === 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
return string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
var repeated = '';
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
|
||||
while (times) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times & 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
repeated += string;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
string += string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : Symbol(trimEnd, Decl(controlFlowPropertyDeclarations.ts, 51, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
: haystack;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : Symbol(hyphenToCamelCase, Decl(controlFlowPropertyDeclarations.ts, 65, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
>match : Symbol(match, Decl(controlFlowPropertyDeclarations.ts, 71, 42))
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : Symbol(isEmpty, Decl(controlFlowPropertyDeclarations.ts, 74, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>/[^\s]/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : Symbol(isConvertiblePixelValue, Decl(controlFlowPropertyDeclarations.ts, 81, 1))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
|
||||
private output: string;
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
|
||||
private level: number;
|
||||
>level : Symbol(HTMLtoJSX.level, Decl(controlFlowPropertyDeclarations.ts, 95, 27))
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : Symbol(HTMLtoJSX._visitText, Decl(controlFlowPropertyDeclarations.ts, 97, 31))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>text .replace(/\r/g, '') .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>JSON.stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>JSON : Symbol(JSON, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
|
||||
styles = {};
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : Symbol(StyleParser.toJSXString, Decl(controlFlowPropertyDeclarations.ts, 140, 14))
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>this.styles.hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,383 @@
|
|||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : any
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>require('react/lib/HTMLDOMPropertyConfig') : any
|
||||
>require : any
|
||||
>'react/lib/HTMLDOMPropertyConfig' : string
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : string
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : boolean
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : any
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty : any
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
>hasOwnProperty : any
|
||||
>propname : string
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase() : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>DOMAttributeNames : any
|
||||
>propname : string
|
||||
>propname.toLowerCase() : string
|
||||
>propname.toLowerCase : () => string
|
||||
>propname : string
|
||||
>toLowerCase : () => string
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : (string: any, times: any) => any
|
||||
>string : any
|
||||
>times : any
|
||||
|
||||
if (times === 1) {
|
||||
>times === 1 : boolean
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
return string;
|
||||
>string : any
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times < 0 : boolean
|
||||
>times : any
|
||||
>0 : number
|
||||
>new Error() : Error
|
||||
>Error : ErrorConstructor
|
||||
|
||||
var repeated = '';
|
||||
>repeated : string
|
||||
>'' : string
|
||||
|
||||
while (times) {
|
||||
>times : any
|
||||
|
||||
if (times & 1) {
|
||||
>times & 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
repeated += string;
|
||||
>repeated += string : string
|
||||
>repeated : string
|
||||
>string : any
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times >>= 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
string += string;
|
||||
>string += string : any
|
||||
>string : any
|
||||
>string : any
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : string
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack.slice(-needle.length) === needle : boolean
|
||||
>haystack.slice(-needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
>needle : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : (haystack: any, needle: any) => any
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith(haystack, needle) ? haystack.slice(0, -needle.length) : haystack : any
|
||||
>endsWith(haystack, needle) : boolean
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack.slice(0, -needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>0 : number
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
|
||||
: haystack;
|
||||
>haystack : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : (string: any) => any
|
||||
>string : any
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string.replace(/-(.)/g, function(match, chr) { return chr.toUpperCase(); }) : any
|
||||
>string.replace : any
|
||||
>string : any
|
||||
>replace : any
|
||||
>/-(.)/g : RegExp
|
||||
>function(match, chr) { return chr.toUpperCase(); } : (match: any, chr: any) => any
|
||||
>match : any
|
||||
>chr : any
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr.toUpperCase() : any
|
||||
>chr.toUpperCase : any
|
||||
>chr : any
|
||||
>toUpperCase : any
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : (string: any) => boolean
|
||||
>string : any
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>!/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test : (string: string) => boolean
|
||||
>/[^\s]/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>string : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : (value: any) => boolean
|
||||
>value : any
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test(value) : boolean
|
||||
>/^\d+px$/.test : (string: string) => boolean
|
||||
>/^\d+px$/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>value : any
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : HTMLtoJSX
|
||||
|
||||
private output: string;
|
||||
>output : string
|
||||
|
||||
private level: number;
|
||||
>level : number
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : boolean
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : (node: any) => void
|
||||
>(node) => { var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase(); if (parentTag === 'textarea' || parentTag === 'style') { // Ignore text content of textareas and styles, as it will have already been moved // to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively. return; } var text = '' if (this._inPreTag) { // If this text is contained within a <pre>, we need to ensure the JSX // whitespace coalescing rules don't eat the whitespace. This means // wrapping newlines and sequences of two or more spaces in variables. text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }); } else { // If there's a newline in the text, adjust the indent level if (text.indexOf('\n') > -1) { } } this.output += text; } : (node: any) => void
|
||||
>node : any
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : any
|
||||
>node.parentNode && node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode.tagName.toLowerCase : any
|
||||
>node.parentNode.tagName : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>tagName : any
|
||||
>toLowerCase : any
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag === 'textarea' || parentTag === 'style' : boolean
|
||||
>parentTag === 'textarea' : boolean
|
||||
>parentTag : any
|
||||
>'textarea' : string
|
||||
>parentTag === 'style' : boolean
|
||||
>parentTag : any
|
||||
>'style' : string
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : string
|
||||
>'' : string
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : boolean
|
||||
>this : this
|
||||
>_inPreTag : boolean
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text : string
|
||||
>text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text .replace(/\r/g, '') .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text .replace(/\r/g, '') : string
|
||||
>text .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text : string
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/\r/g : RegExp
|
||||
>'' : string
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/( {2,}|\n|\t|\{|\})/g : RegExp
|
||||
>function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; } : (whitespace: string) => string
|
||||
>whitespace : string
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>'{' + JSON.stringify(whitespace) + '}' : string
|
||||
>'{' + JSON.stringify(whitespace) : string
|
||||
>'{' : string
|
||||
>JSON.stringify(whitespace) : string
|
||||
>JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>JSON : JSON
|
||||
>stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>whitespace : string
|
||||
>'}' : string
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf('\n') > -1 : boolean
|
||||
>text.indexOf('\n') : number
|
||||
>text.indexOf : (searchString: string, position?: number) => number
|
||||
>text : string
|
||||
>indexOf : (searchString: string, position?: number) => number
|
||||
>'\n' : string
|
||||
>-1 : number
|
||||
>1 : number
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output += text : string
|
||||
>this.output : string
|
||||
>this : this
|
||||
>output : string
|
||||
>text : string
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : StyleParser
|
||||
|
||||
styles = {};
|
||||
>styles : {}
|
||||
>{} : {}
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : () => void
|
||||
>() => { for (var key in this.styles) { if (!this.styles.hasOwnProperty(key)) { } } } : () => void
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : string
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>!this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty : (v: string) => boolean
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
>hasOwnProperty : (v: string) => boolean
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
private output: string;
|
||||
private level: number;
|
||||
private _inPreTag: boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
|
||||
if (this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
styles = {};
|
||||
toJSXString = () => {
|
||||
for (var key in this.styles) {
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче