blob: 5ee6ebc83e7726f1ba167429eb21424f2a4e08e0 [file] [log] [blame]
function traverse(schema, rootName, cb) {
function innerTraverse(schemaNode, path, noCallback) {
if (!noCallback) {
cb(path, schemaNode);
}
if (schemaNode.items) {
if (schemaNode.items.anyOf) {
schemaNode.items.anyOf.forEach(itemSchema => {
let typeValue = itemSchema.properties
&& itemSchema.properties.type
&& itemSchema.properties.type.default;
if (typeValue) {
innerTraverse(
itemSchema,
path ? (path + '-' + typeValue.replace(/'/g, '')) : typeValue,
false
);
}
});
}
else {
innerTraverse(schemaNode.items, path, true);
}
}
else if (schemaNode.properties) {
for (let propName in schemaNode.properties) {
innerTraverse(
schemaNode.properties[propName],
path ? (path + '.' + propName) : propName,
false
);
}
}
// Or it's a leaf node.
}
innerTraverse(schema.option, rootName, false);
};
module.exports.traverse = traverse;
function convertToTree(rootSchema, rootNode) {
function createNodeBase(schema) {
let schemaType = schema.type;
// Simplify type
if (schemaType instanceof Array && schemaType.length === 1) {
schemaType = schemaType[0];
}
let nodeBase = {};
// Get type from default if possible. Reduce size.
if (schema.default == null || typeof schema.default !== schemaType) {
nodeBase.type = schemaType;
}
if (schema.default != null) {
nodeBase.default = schema.default;
}
if (schema.items) { // Array also may has properties.
nodeBase.isArray = true;
}
else if (schema.properties && Object.keys(schema.properties).length) {
nodeBase.isObject = true;
}
return nodeBase;
}
function createArrayItemNode(schema, parentNode) {
let childNode = createNodeBase(schema, parentNode);
if (schema.properties && schema.properties.type && schema.properties.type.default) {
childNode.arrayItemType = schema.properties.type.default.replace(/'/g, '');
}
else {
console.error('schema', schema);
throw new Error('Some thing wrong happens');
}
return childNode;
}
function createPropertyNode(propName, schema, parentNode) {
let childNode = createNodeBase(schema, parentNode);
childNode.prop = propName;
return childNode;
}
function processObjectType(currentSchema, currentNode) {
if (!currentSchema.properties) {
return;
}
let children = [];
for (let propName in currentSchema.properties) {
let childSchema = currentSchema.properties[propName];
let childNode = createPropertyNode(propName, childSchema, currentNode);
processRecursively(childSchema, childNode);
children.push(childNode);
}
if (children.length) {
currentNode.children = children;
}
}
function processArrayType(currentSchema, currentNode) {
if (!currentSchema.items) {
return;
}
// Each item of array may have different type of object.
// Like series, visualMap, legend
if (currentSchema.items.anyOf) {
let children = [];
currentSchema.items.anyOf.forEach(itemSchema => {
let childNode = createArrayItemNode(itemSchema, currentNode);
processRecursively(itemSchema, childNode);
children.push(childNode);
});
currentNode.children = children;
}
// Each item of array only have one type of object.
// Like data and most of the compoents.
else {
processObjectType(
currentSchema.items, currentNode
);
}
}
function processRecursively(currentSchema, currentNode) {
// Array also may has properties.
if (currentSchema.items) {
processArrayType(currentSchema, currentNode);
}
else if (currentSchema.properties) {
processObjectType(currentSchema, currentNode);
}
return currentNode;
}
return processRecursively(
rootSchema, rootNode, 0
);
};
module.exports.extractOptionKeys = function (schema) {
const keysRepeatCount = {};
const keysList = [];
traverse(schema, '', (schemaPath, schemaNode) => {
if (!schemaPath) {
return;
}
const leafKey = schemaPath.split(/[\.-]/g).pop();
if (keysRepeatCount[leafKey] == null) {
keysRepeatCount[leafKey] = 0;
keysList.push(leafKey);
}
keysRepeatCount[leafKey]++;
});
return keysList.map(key => {
return {
name: key,
count: keysRepeatCount[key]
};
}).sort((a, b) => b.count - a.count);
};
// Partion the descriptions by the first part of path. For example
// { "title.label", "series-line.data", "series-bar.data" }
// Will be
// {
// "title": { "label" },
// "series-line": {"data"},
// "series-bar": {"data"}
// }
module.exports.extractDesc = function (schema, docName) {
let descriptionsMap = {};
let propWithUIControlCount = 0;
let propTotalCount = 0;
traverse(schema, docName, (schemaPath, schemaNode) => {
if (schemaNode.description) {
// Extract component level path
let parts = schemaPath.split('.');
let divider = parts.length > 2 ? 2 : 1;
let partionKey = parts.slice(0, divider).join('.');
let subKey = parts.slice(divider).join('.');
descriptionsMap[partionKey] = descriptionsMap[partionKey] || {};
descriptionsMap[partionKey][subKey] = {
desc: schemaNode.description,
exampleBaseOptions: schemaNode.exampleBaseOptions,
uiControl: schemaNode.uiControl
};
propTotalCount++;
if (schemaNode.uiControl) {
propWithUIControlCount++;
}
}
});
console.log(`Options with UIControl ${propWithUIControlCount} / ${propTotalCount} (${propWithUIControlCount/propTotalCount})`);
return {
outline: convertToTree(schema.option, {}),
descriptions: descriptionsMap
};
};