@lottiefiles/relottie-parse
Version:
Parse Lottie JSON format to LAST
326 lines (324 loc) • 11.2 kB
JavaScript
import { getNoKeyEntity, getMemberEntity } from './chunk-5KELHOJY.js';
import { fileConstants } from './chunk-X5PT7L37.js';
import { ar, ob, rt, pt, at, el, cl, ky } from '@lottiefiles/last-builder';
import { is } from 'unist-util-is';
var createValueType = (node, options) => {
if (!options.valueType || node.type === "Element" || node.type === "Object" || node.type === "Document") {
return {};
}
return { valueType: node.type.toLowerCase() };
};
var createPositionProp = (node, options) => {
if (options.position) {
return {
position: { ...node.loc }
};
} else {
return {};
}
};
var getPrimitiveNodeValue = (node) => {
switch (node.type) {
case "Boolean":
return node.value;
case "Number":
return node.value;
case "String":
return node.value;
case "Null":
return null;
case "NaN":
return null;
case "Infinity":
return null;
case "Identifier":
return null;
default:
return null;
}
};
var createPrimitiveNode = (node, options) => {
const position = createPositionProp(node, options);
const valueType = createValueType(node, options);
const value = getPrimitiveNodeValue(node);
return pt(value, { ...position, ...valueType });
};
var createKeyNode = (node, options) => {
const value = node.name.type === "String" ? node.name.value : node.name.name;
if (options.position) {
const posiiton = createPositionProp(node.name, options);
return ky(value, { ...posiiton });
} else {
return value;
}
};
var createMemberNode = (node, parentTitle, options) => {
const keyValue = createKeyNode(node, options);
const key = typeof keyValue === "string" ? keyValue : keyValue.value;
const position = createPositionProp(node, options);
const parts = {
...position
};
const { title } = getMemberEntity(key, node, parentTitle);
switch (node.value.type) {
case "Array":
return cl(keyValue, title, [], { ...parts });
case "Object":
return el(keyValue, title, [], { ...parts });
default:
return at(keyValue, title, [], { ...parts });
}
};
var isMomoaMemberValue = (node, parent) => {
const nodeType = node.type;
if (nodeType === "Identifier" || nodeType === "NaN" || nodeType === "Infinity") return false;
return parent.loc.end.column === node.loc.end.column;
};
function assertNodeType(node, type, file) {
if (!is(node, type)) {
file.fail(`Unexpected node type found ${node?.type}, has to be ${type}`);
}
}
var getMembersFromArrNode = (node) => {
const members = [];
node.elements.forEach((element) => {
const elementValue = element.value;
if (is(elementValue, "Object")) {
elementValue.members.forEach((member) => members.push(member));
}
});
return members;
};
var getTitleFromMemberValue = (node, parentNodeTitle, dependent, file) => {
const { key, parentTitle, type } = dependent;
switch (type) {
case "Constant":
if (!is(node, "String") && !is(node, "Number")) break;
const { defaultValue, prefix, values } = parentTitle;
const defaultConstTitle = values[defaultValue];
if (!defaultConstTitle)
throw new Error(`[${parentNodeTitle}] '${defaultValue}' has to present in "dependent.parentTitle.values"`);
const constantKey = node.value;
const constTitle = values[constantKey];
if (!constTitle) {
const message = `[${parentNodeTitle}] '${constantKey}' is missing in "dependent.parentTitle.values"`;
file.message(message, node, fileConstants.sourceId);
}
const title = typeof constTitle === "undefined" ? defaultConstTitle : constTitle;
return prefix && prefix.length > 0 ? `${prefix}-${title}` : title;
case "Array":
if (!is(node, "Array")) break;
const childType = dependent.childType;
const matchedMember = childType ? node.elements.find((element) => element.value.type === childType) : void 0;
if (!matchedMember) break;
return parentTitle;
default:
if (type !== node.type) {
const message = `${parentNodeTitle}'s '${key}' type is ${node.type} but has to be ${type}`;
file.message(message, node, fileConstants.sourceId);
break;
}
return parentTitle;
}
return void 0;
};
var getDependentTitle = (parentTitle, members, dependents, file) => {
const memberKeyValue = members.reduce((acc, member) => {
const memberName = member.name;
const key = memberName.type === "String" ? memberName.value : memberName.name;
acc[key] = member.value;
return acc;
}, {});
for (const dependent of dependents) {
const { key } = dependent;
const node = memberKeyValue[key];
if (!node) continue;
const title = getTitleFromMemberValue(node, parentTitle, dependent, file);
if (title) return title;
}
return void 0;
};
var getObjectNodeTitle = (node, parentNodeTitle, file) => {
const entity = getNoKeyEntity(node, parentNodeTitle);
const { defaultTitle, dependents } = entity;
if (!dependents) return defaultTitle;
const title = getDependentTitle(parentNodeTitle, node.members, dependents, file);
return title || defaultTitle;
};
var getArrayNodeTitle = (node, parentNodeTitle, file) => {
const entity = getNoKeyEntity(node, parentNodeTitle);
const { defaultTitle, dependents } = entity;
if (!dependents) return defaultTitle;
const members = getMembersFromArrNode(node);
const title = getDependentTitle(parentNodeTitle, members, dependents, file);
return title || defaultTitle;
};
var traverseJsonEnter = (node, parent, stack, file, options) => {
const position = createPositionProp(node, options);
switch (node.type) {
case "Document":
if (node.body.type !== "Object") {
file.fail(new Error(`Lottie must be "Object" but it's "${node.body.type}"`));
}
break;
case "Member":
const memberParent = stack.peek();
stack.push(createMemberNode(node, memberParent.title, options));
break;
case "Object":
if (!parent) break;
switch (parent.type) {
case "Document":
stack.push(rt([], { ...position }));
break;
case "Member":
const element = stack.peek();
assertNodeType(element, "element", file);
const elementValueTitle = getObjectNodeTitle(node, element.title, file);
stack.push(ob(elementValueTitle, [], { ...position }));
break;
case "Element":
const array = stack.peek();
assertNodeType(array, "array", file);
const objectTitle = getObjectNodeTitle(node, array.title, file);
stack.push(ob(objectTitle, [], { ...position }));
break;
}
break;
case "Element":
break;
case "Array":
if (!parent) break;
switch (parent.type) {
case "Member":
const collection = stack.peek();
assertNodeType(collection, "collection", file);
const collectionValueTitle = getArrayNodeTitle(node, collection.title, file);
stack.push(ar(collectionValueTitle, [], { ...position }));
break;
case "Element":
const array = stack.peek();
assertNodeType(array, "array", file);
const arrayTitle = getArrayNodeTitle(node, array.title, file);
stack.push(ar(arrayTitle, [], { ...position }));
break;
}
break;
default:
if (!parent) break;
switch (parent.type) {
case "Member":
if (isMomoaMemberValue(node, parent)) {
stack.push(createPrimitiveNode(node, options));
}
break;
case "Element":
stack.push(createPrimitiveNode(node, options));
break;
}
break;
}
};
var traverseJsonExit = (node, parent, stack, file, _options, info = {}) => {
switch (node.type) {
case "Document":
break;
case "Member":
const objectNodeValue = stack.pop();
const parentNode = stack.peek();
if (parentNode.type === "root") {
parentNode.children.push(objectNodeValue);
break;
}
switch (objectNodeValue.type) {
case "element":
info.slots?.setNode(objectNodeValue, parentNode, node);
break;
case "collection":
break;
case "attribute":
if (!info.hasExpressions && objectNodeValue.title === "expression") {
info.hasExpressions = true;
break;
}
info.slots?.setIdTitle(objectNodeValue, parentNode);
break;
default:
file.fail("Node's type has to be 'element', 'collection' or 'attribute'");
}
parentNode.children.push(objectNodeValue);
break;
case "Object":
if (!parent) break;
switch (parent.type) {
case "Document":
break;
case "Member":
const elementChild = stack.pop();
assertNodeType(elementChild, "object", file);
const element = stack.peek();
assertNodeType(element, "element", file);
if (elementChild.title === element.title) {
elementChild.title = `${element.title}-children`;
}
element.children = [elementChild];
break;
case "Element":
const arrayChild = stack.pop();
assertNodeType(arrayChild, "object", file);
const array = stack.peek();
assertNodeType(array, "array", file);
array.children.push(arrayChild);
break;
}
break;
case "Element":
break;
case "Array":
if (!parent) break;
switch (parent.type) {
case "Member":
const collectionChild = stack.pop();
assertNodeType(collectionChild, "array", file);
const collection = stack.peek();
assertNodeType(collection, "collection", file);
if (collectionChild.title === collection.title) {
collectionChild.title = `${collection.title}-children`;
}
collection.children = [collectionChild];
break;
case "Element":
const arrayChild = stack.pop();
assertNodeType(arrayChild, "array", file);
const array = stack.peek();
assertNodeType(array, "array", file);
array.children.push(arrayChild);
break;
}
break;
default:
if (!parent) break;
switch (parent.type) {
case "Member":
if (isMomoaMemberValue(node, parent)) {
const attributeChild = stack.pop();
assertNodeType(attributeChild, "primitive", file);
const attribute = stack.peek();
assertNodeType(attribute, "attribute", file);
attribute.children = [attributeChild];
}
break;
case "Element":
const arrayChild = stack.pop();
assertNodeType(arrayChild, "primitive", file);
const array = stack.peek();
assertNodeType(array, "array", file);
array.children.push(arrayChild);
break;
}
break;
}
};
export { getPrimitiveNodeValue, traverseJsonEnter, traverseJsonExit };
//# sourceMappingURL=chunk-IIN7RTEO.js.map
//# sourceMappingURL=chunk-IIN7RTEO.js.map