@babel/traverse#Node TypeScript Examples
The following examples show how to use
@babel/traverse#Node.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: code-utils.ts From plasmic with MIT License | 7 votes |
nodeToFormattedCode = (
n: Node,
baseDir: string,
unformatted?: boolean,
commentsToRemove?: Set<string>
) => {
const c = generate(n, {
retainLines: true,
shouldPrintComment: (c) => !commentsToRemove || !commentsToRemove.has(c),
}).code;
return unformatted
? c
: formatAsLocal(c, "/tmp/x.tsx", baseDir, {
trailingComma: "none",
arrowParens: "avoid",
});
}
Example #2
Source File: utils.ts From plasmic with MIT License | 7 votes |
code = (
n: Node | undefined,
opts?: GeneratorOptions,
unformatted?: boolean
) => {
assert(n);
const c = generate(n, opts).code;
return unformatted ? c : formatted(c);
}
Example #3
Source File: plasmic-parser-test.ts From plasmic with MIT License | 6 votes |
getSource = (n: Node | null, input: string) => {
if (!n) {
return undefined;
}
if (n.start === null || n.end === null) {
return undefined;
}
return input.substring(n.start, n.end);
}
Example #4
Source File: utils.ts From plasmic with MIT License | 6 votes |
nodesDeepEqualIgnoreComments = (n1: Node, n2: Node) => {
return compactCode(n1) === compactCode(n2);
}
Example #5
Source File: utils.ts From plasmic with MIT License | 6 votes |
compactCode = (n: Node) => {
return code(n, { comments: false, compact: true }, true);
}
Example #6
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
isCallWithoutArguments = (
call: Node,
object: string,
member: string
) => {
return (
isCallIgnoreArguments(call, object, member) && call.arguments.length === 0
);
}
Example #7
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
isCallIgnoreArguments = (
call: Node,
object: string,
member: string
): call is CallExpression => {
if (call.type !== "CallExpression") {
return false;
}
return memberExpressionMatch(call.callee, object, member);
}
Example #8
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
memberExpressionMatch = (
node: Node,
object: string,
member?: string
) => {
if (node.type !== "MemberExpression") {
return false;
}
return (
node.object.type === "Identifier" &&
node.object.name === object &&
node.property.type === "Identifier" &&
node.property.name === member
);
}
Example #9
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
tryExtractPropertyNameOfMemberExpression = (
callee: Node,
object: string
) => {
if (callee.type !== "MemberExpression") {
return undefined;
}
if (
callee.object.type === "Identifier" &&
callee.object.name === object &&
callee.property.type === "Identifier"
) {
return callee.property.name as string;
}
return undefined;
}
Example #10
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
parseNode = (
n:
| Expression
| JSXEmptyExpression
| JSXExpressionContainer
| JSXSpreadChild
| JSXFragment,
parent: Node | undefined,
forceFragmentAsOneNode: boolean
): PlasmicASTNode => {
let node: PlasmicASTNode | null = null;
if (n.type === "JSXExpressionContainer") {
// Always unwrap the expression container
node = parseNode(n.expression, n, forceFragmentAsOneNode);
} else if (n.type === "JSXSpreadChild") {
node = parseAsOneNode(n.expression, n);
} else if (n.type === "JSXFragment") {
node = forceFragmentAsOneNode
? parseAsOneNode(n, parent)
: {
type: "jsx-fragment",
children: parseChildren(n),
rawNode: n,
};
} else {
node = parseAsOneNode(n, parent);
}
node.rawNode = n;
return node;
}
Example #11
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
tryParseAsPlasmicJsxElement = (
jsx: JSXElement,
parent: Node | undefined
): PlasmicJsxElement | undefined => {
let nodeId: string | undefined = undefined;
for (const attr of jsx.openingElement.attributes) {
const curNodeId = tryGetNodeIdFromAttr(attr);
if (curNodeId) {
if (nodeId) {
// The id in className and spreador must match.
assert(nodeId === curNodeId);
}
nodeId = curNodeId;
}
}
return nodeId ? parseJsxElement(jsx, nodeId, parent) : undefined;
}
Example #12
Source File: plasmic-parser.ts From plasmic with MIT License | 6 votes |
parseJsxElement = (
n: JSXElement,
plasmicId: string,
parent: Node | undefined
): PlasmicJsxElement => {
const attrs: Array<[string, PlasmicASTNode | null] | PlasmicASTNode> =
n.openingElement.attributes.map((attr) => {
if (attr.type === "JSXAttribute") {
const name = getAttrName(attr);
assert(L.isString(name));
return [
name,
attr.value === null
? null
: parseNode(attr.value as any, attr, false),
];
} else {
// spreador
return parseNode(attr.argument, attr, false);
}
});
const children = parseChildren(n);
return {
attrs,
children,
rawNode: n,
rawParent: parent,
nameInId: plasmicId,
};
}
Example #13
Source File: plasmic-parser.ts From plasmic with MIT License | 5 votes |
isJsxElementOrFragment = (n: Node) => {
return n.type === "JSXElement" || n.type === "JSXFragment";
}
Example #14
Source File: plasmic-parser.ts From plasmic with MIT License | 5 votes |
parseAsOneNode = (
n: Expression | JSXEmptyExpression | JSXFragment,
parent: Node | undefined
): PlasmicASTNode => {
if (n.type === "JSXEmptyExpression") {
return {
type: "opaque",
rawNode: n,
};
}
if (n.type === "StringLiteral") {
return {
type: "string-lit",
value: n.value,
rawNode: n,
};
}
if (n.type === "CallExpression") {
const callee = tryExtractPropertyNameOfMemberExpression(
n.callee,
helperObject
);
const m = callee?.match(/^childStr(.+)$/);
if (m) {
return { type: "child-str-call", plasmicId: ensure(m[1]), rawNode: n };
}
}
// Need to handle this case specially since traverse doesn't visit n itself.
if (n.type === "JSXElement") {
const jsxElement = tryParseAsPlasmicJsxElement(n, parent);
if (jsxElement) {
return {
type: "tag-or-component",
jsxElement,
rawNode: n,
secondaryNodes: [],
};
}
}
const jsxElements: PlasmicJsxElement[] = [];
traverse(n, {
noScope: true,
JSXElement: function (path) {
const jsxElement = tryParseAsPlasmicJsxElement(path.node, path.parent);
if (jsxElement) {
jsxElements.push(jsxElement);
path.skip();
}
},
});
return jsxElements.length > 0
? {
type: "tag-or-component",
jsxElement: jsxElements[0],
rawNode: n,
secondaryNodes: jsxElements.slice(1).map((elt) => ({
type: "tag-or-component",
jsxElement: elt,
rawNode:
elt.rawParent && elt.rawParent.type === "LogicalExpression"
? elt.rawParent
: elt.rawNode,
secondaryNodes: [],
})),
}
: {
type: "opaque",
rawNode: n,
};
}
Example #15
Source File: plasmic-parser.ts From plasmic with MIT License | 5 votes |
renameJsxTree(targetCodeVersion: CodeVersion) {
const revisedNameInIdToUuid = new Map<string, string>(
targetCodeVersion.nameInIdToUuid
);
const renamedJsx = cloneDeepWithHook(this.root.rawNode, (n: Node) => {
const helperMember = tryExtractPropertyNameOfMemberExpression(
n,
helperObject
);
if (helperMember) {
const eventHandlers = [
"onMouseUp",
"onMouseDown",
"onFocus",
"onBlur",
"onMouseEnter",
"onMouseLeave",
];
const regEx = new RegExp(
`^(cls|props|show|childStr|${eventHandlers.join("|")})(.+)$`
);
const m = helperMember.match(regEx);
if (m) {
const prefix = m[1];
const nameInId = m[2];
const curUuid = ensure(this.nameInIdToUuid.get(nameInId));
const newNameInId = targetCodeVersion.findMatchingNameInId({
nameInId,
uuid: curUuid,
});
if (!newNameInId) {
// node has been deleted in targetCodeVersion. Fine to keep the name,
// but need to add this id into the new map.
revisedNameInIdToUuid.set(nameInId, curUuid);
} else {
return makeMemberExpression(
helperObject,
`${prefix}${newNameInId}`
);
}
}
return undefined;
}
const argName = tryExtractPropertyNameOfMemberExpression(n, "args");
if (argName) {
const newSlotArgName = targetCodeVersion.findMatchingSlotArgName(
argName,
this.tryGetSlotArgUuid(argName)
);
if (!newSlotArgName) {
// Either non slot args, or the arg has been deleted. Keep the name
} else {
return makeMemberExpression("args", newSlotArgName);
}
}
return undefined;
});
assert(babel.types.isExpression(renamedJsx));
return new CodeVersion(renamedJsx, revisedNameInIdToUuid);
}
Example #16
Source File: plasmic-parser-test.ts From plasmic with MIT License | 5 votes |
assertJsxExpressionContainer = (node: Node | undefined, tag: string) => {
assert(node);
assert(node.type === "JSXExpressionContainer");
}
Example #17
Source File: plasmic-parser-test.ts From plasmic with MIT License | 5 votes |
assertJsxElement = (node: Node | undefined) => {
assert(node);
assert(node.type === "JSXElement");
}
Example #18
Source File: index.ts From plasmic with MIT License | 4 votes |
mergeFiles = async (
componentByUuid: Map<string, ComponentInfoForMerge>,
projectId: string,
projectSyncDataProvider: ProjectSyncDataProviderType,
preMergeFile?: (
compId: string,
baseSrc: string,
baseNameInIdToUuid: Map<string, string>,
newSrc: string,
newNameInIdToUuid: Map<string, string>
) => void,
appendJsxTreeOnMissingBase?: boolean,
// Output parameter, which is used to collect warning information
warningInfos?: Map<string, WarningInfo>
) => {
const updateableByComponentUuid = new Map<
string,
PlasmicComponentSkeletonFile
>();
componentByUuid.forEach((codeVersions, uuid) => {
const parsedEdited = tryParseComponentSkeletonFile(codeVersions.editedFile);
if (parsedEdited) {
updateableByComponentUuid.set(uuid, parsedEdited);
}
});
if (updateableByComponentUuid.size === 0) {
// Nothing to update
return undefined;
}
const mergedFiles = new Map<string, string>();
for (const [componentUuid, parsedEdited] of updateableByComponentUuid) {
const warnInfo = new WarningInfo();
warningInfos?.set(componentUuid, warnInfo);
let baseMetadata: ComponentSkeletonModel | undefined = undefined;
try {
const projectSyncData = await projectSyncDataProvider(
projectId,
parsedEdited.revision
);
baseMetadata = projectSyncData.components.find(
(c) => c.uuid === componentUuid
);
} catch {
warnInfo.addRawWarn(
`missing merging base for ${projectId} at revision ${parsedEdited.revision}`
);
}
const component = ensure(componentByUuid.get(componentUuid));
const parsedNew = ensure(tryParseComponentSkeletonFile(component.newFile));
if (!baseMetadata) {
if (appendJsxTreeOnMissingBase) {
mergedFiles.set(
componentUuid,
formatted(`${component.editedFile}
// Please perform merge with the following JSX manually.
\`// plasmic-managed-jsx/${parsedNew.revision}
return (${code(parsedNew.jsx).trimEnd()});\``)
);
continue;
} else {
throw new Error(
`Cannot perform three way merge due to missing base version. For Plasmic CLI users, please add '--append-jsx-on-missing-base' so that you can perform merging by yourselves.`
);
}
}
if (preMergeFile) {
preMergeFile(
componentUuid,
baseMetadata.fileContent,
baseMetadata.nameInIdToUuid,
component.newFile,
component.newNameInIdToUuid
);
}
const parsedBase = ensure(
tryParseComponentSkeletonFile(baseMetadata.fileContent)
);
const newCodeVersion = new CodeVersion(
parsedNew.jsx,
component.newNameInIdToUuid
);
const baseCodeVersion = new CodeVersion(
parsedBase.jsx,
baseMetadata.nameInIdToUuid
);
// All other metadata
const editedCodeVersion = new CodeVersion(
parsedEdited.jsx,
// edited version share the same nameInIdtoUuid mapping
baseMetadata.nameInIdToUuid
);
warnInfo.setSecondaryNodes([
...editedCodeVersion.secondaryTagsOrComponents.values(),
]);
const newJsx = renameAndSerializePlasmicASTNode(newCodeVersion.root, {
newVersion: newCodeVersion,
editedVersion: editedCodeVersion,
baseVersion: baseCodeVersion,
});
// Ideally, we should keep parsedEdited read-only, but, it is not a big deal
// to modify the comment.
parsedEdited.identifyingComment.value = ` plasmic-managed-jsx/${parsedNew.revision}`;
const mergedFile = cloneDeepWithHook(parsedEdited.file, (n: Node) => {
if (n === parsedEdited.jsx) {
return newJsx;
}
return undefined;
});
mergePlasmicImports(mergedFile, parsedNew, parsedEdited);
const mergedCode = code(mergedFile, { retainLines: true });
mergedFiles.set(componentUuid, formatted(mergedCode));
}
return mergedFiles;
}
Example #19
Source File: index.ts From plasmic with MIT License | 4 votes |
serializeTagOrComponent = (
newNode: PlasmicTagOrComponent,
codeVersions: CodeVersions
): Expression | JSXExpressionContainer | undefined => {
const { newVersion, editedVersion, baseVersion } = codeVersions;
// find node with same id in edited version.
const editedNode = editedVersion.findTagOrComponent(
newNode.jsxElement.nameInId
);
const baseNode = baseVersion.findTagOrComponent(newNode.jsxElement.nameInId);
if (editedNode) {
// the node must exist in base version.
assert(!!baseNode);
const editedNodeJsxElementClone = babel.types.cloneDeep(
editedNode.jsxElement.rawNode
);
editedNodeJsxElementClone.openingElement.name = mergedTag(
newNode,
editedNode,
baseNode
);
if (editedNodeJsxElementClone.closingElement) {
editedNodeJsxElementClone.closingElement.name =
editedNodeJsxElementClone.openingElement.name;
}
editedNodeJsxElementClone.openingElement.attributes = mergeAttributes(
newNode,
editedNode,
baseNode,
codeVersions
);
editedNodeJsxElementClone.children = mergedChildren(
newNode,
editedNode,
baseNode,
codeVersions
);
if (
!editedNodeJsxElementClone.closingElement &&
editedNodeJsxElementClone.children.length > 0
) {
editedNodeJsxElementClone.closingElement = babel.types.jsxClosingElement(
editedNodeJsxElementClone.openingElement.name
);
editedNodeJsxElementClone.openingElement.selfClosing = false;
}
const secondaryNodes = new Map<Node, Node | undefined>(
editedNode.secondaryNodes.map((n) => {
const newSecondaryNode = newVersion.findTagOrComponent(
n.jsxElement.nameInId
);
if (!newSecondaryNode) {
return [n.rawNode, undefined];
}
const rawReplacement = serializePlasmicASTNode(
newSecondaryNode,
codeVersions
);
return [n.rawNode, rawReplacement];
})
);
const newNodeCallShowFunc = newVersion.hasShowFuncCall(newNode);
const editedNodeCallShowFunc = editedVersion.hasShowFuncCall(editedNode);
const editedNodeClone = cloneDeepWithHook(editedNode.rawNode, (n: Node) => {
if (n === editedNode.jsxElement.rawNode) {
if (newNodeCallShowFunc && !editedNodeCallShowFunc) {
// add the show call
const expr = makeJsxElementWithShowCall(
editedNodeJsxElementClone,
editedNode.jsxElement.nameInId
);
// add an expression container if the parent is JSXElement or Fragment
return editedNode.jsxElement.rawParent &&
isJsxElementOrFragment(editedNode.jsxElement.rawParent)
? wrapInJsxExprContainer(expr)
: expr;
}
return editedNodeJsxElementClone;
}
if (secondaryNodes.has(n)) {
const replacement = secondaryNodes.get(n);
// If deleted, an empty fragment instead
return replacement || mkJsxFragment([]);
}
return undefined;
});
if (editedNodeCallShowFunc && !newNodeCallShowFunc) {
traverse(editedNodeClone, {
noScope: true,
CallExpression: function (path) {
if (
isCallIgnoreArguments(
path.node,
helperObject,
`show${editedNode.jsxElement.nameInId}`
)
) {
path.replaceWithSourceString("true");
}
},
});
}
return editedNodeClone;
}
// check if the node has been deleted.
if (baseNode) {
// If so, don't output anything
return undefined;
}
// This is new node. Just output self.
const childrenReplacement = new Map<Node, Node>();
newNode.jsxElement.children.forEach((child) => {
// Plasmic never emit opaque node.
assert(child.type !== "opaque");
const childReplacement = serializeNonOpaquePlasmicASTNode(
child,
codeVersions
);
if (childReplacement) {
if (babel.types.isExpression(childReplacement)) {
// need to wrap in expression container
const maybeWrapped =
childReplacement.type !== "JSXElement" &&
childReplacement.type !== "JSXFragment"
? babel.types.jsxExpressionContainer(childReplacement)
: childReplacement;
childrenReplacement.set(child.rawNode, maybeWrapped);
} else {
childrenReplacement.set(child.rawNode, childReplacement);
}
}
});
// Attribute replacement
const attrsReplacement = new Map<Node, Node>();
newNode.jsxElement.attrs.forEach((attr) => {
if (L.isArray(attr)) {
const [key, value] = attr;
// className is an opaque attribute!
if (value && value.type !== "opaque") {
const attrReplacement = serializeNonOpaquePlasmicASTNode(
value,
codeVersions
);
if (attrReplacement) {
if (attrReplacement.type !== "JSXExpressionContainer") {
assert(attrReplacement.type !== "JSXText");
attrsReplacement.set(
value.rawNode,
babel.types.jsxExpressionContainer(attrReplacement)
);
} else {
attrsReplacement.set(value.rawNode, attrReplacement);
}
}
}
}
});
return cloneDeepWithHook(
newNode.rawNode,
(n: Node) => childrenReplacement.get(n) || attrsReplacement.get(n)
);
}