Files
react/vendor/fbtransform/transforms/xjs.js
Paul O’Shannessy dcf415c2b9 BSD + PATENTS
2014-10-10 13:34:07 -07:00

248 lines
4.8 KiB
JavaScript

/**
* Copyright 2013-2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/*global exports:true*/
"use strict";
var Syntax = require('esprima-fb').Syntax;
var utils = require('jstransform/src/utils');
var knownTags = {
a: true,
abbr: true,
address: true,
applet: true,
area: true,
article: true,
aside: true,
audio: true,
b: true,
base: true,
bdi: true,
bdo: true,
big: true,
blockquote: true,
body: true,
br: true,
button: true,
canvas: true,
caption: true,
circle: true,
cite: true,
code: true,
col: true,
colgroup: true,
command: true,
data: true,
datalist: true,
dd: true,
defs: true,
del: true,
details: true,
dfn: true,
dialog: true,
div: true,
dl: true,
dt: true,
ellipse: true,
em: true,
embed: true,
fieldset: true,
figcaption: true,
figure: true,
footer: true,
form: true,
g: true,
h1: true,
h2: true,
h3: true,
h4: true,
h5: true,
h6: true,
head: true,
header: true,
hgroup: true,
hr: true,
html: true,
i: true,
iframe: true,
img: true,
input: true,
ins: true,
kbd: true,
keygen: true,
label: true,
legend: true,
li: true,
line: true,
linearGradient: true,
link: true,
main: true,
map: true,
mark: true,
marquee: true,
mask: false,
menu: true,
menuitem: true,
meta: true,
meter: true,
nav: true,
noscript: true,
object: true,
ol: true,
optgroup: true,
option: true,
output: true,
p: true,
param: true,
path: true,
pattern: false,
picture: true,
polygon: true,
polyline: true,
pre: true,
progress: true,
q: true,
radialGradient: true,
rect: true,
rp: true,
rt: true,
ruby: true,
s: true,
samp: true,
script: true,
section: true,
select: true,
small: true,
source: true,
span: true,
stop: true,
strong: true,
style: true,
sub: true,
summary: true,
sup: true,
svg: true,
table: true,
tbody: true,
td: true,
text: true,
textarea: true,
tfoot: true,
th: true,
thead: true,
time: true,
title: true,
tr: true,
track: true,
tspan: true,
u: true,
ul: true,
'var': true,
video: true,
wbr: true
};
function renderXJSLiteral(object, isLast, state, start, end) {
var lines = object.value.split(/\r\n|\n|\r/);
if (start) {
utils.append(start, state);
}
var lastNonEmptyLine = 0;
lines.forEach(function (line, index) {
if (line.match(/[^ \t]/)) {
lastNonEmptyLine = index;
}
});
lines.forEach(function (line, index) {
var isFirstLine = index === 0;
var isLastLine = index === lines.length - 1;
var isLastNonEmptyLine = index === lastNonEmptyLine;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, ' ');
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, '');
}
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
}
if (!isFirstLine) {
utils.append(line.match(/^[ \t]*/)[0], state);
}
if (trimmedLine || isLastNonEmptyLine) {
utils.append(
JSON.stringify(trimmedLine) +
(!isLastNonEmptyLine ? " + ' ' +" : ''),
state);
if (isLastNonEmptyLine) {
if (end) {
utils.append(end, state);
}
if (!isLast) {
utils.append(', ', state);
}
}
// only restore tail whitespace if line had literals
if (trimmedLine && !isLastLine) {
utils.append(line.match(/[ \t]*$/)[0], state);
}
}
if (!isLastLine) {
utils.append('\n', state);
}
});
utils.move(object.range[1], state);
}
function renderXJSExpressionContainer(traverse, object, isLast, path, state) {
// Plus 1 to skip `{`.
utils.move(object.range[0] + 1, state);
traverse(object.expression, path, state);
if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) {
// If we need to append a comma, make sure to do so after the expression.
utils.catchup(object.expression.range[1], state, trimLeft);
utils.append(', ', state);
}
// Minus 1 to skip `}`.
utils.catchup(object.range[1] - 1, state, trimLeft);
utils.move(object.range[1], state);
return false;
}
function quoteAttrName(attr) {
// Quote invalid JS identifiers.
if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) {
return "'" + attr + "'";
}
return attr;
}
function trimLeft(value) {
return value.replace(/^[ ]+/, '');
}
exports.knownTags = knownTags;
exports.renderXJSExpressionContainer = renderXJSExpressionContainer;
exports.renderXJSLiteral = renderXJSLiteral;
exports.quoteAttrName = quoteAttrName;
exports.trimLeft = trimLeft;