mirror of
https://github.com/VisActor/VTable
synced 2024-11-22 01:52:03 +00:00
227 lines
6.8 KiB
JavaScript
227 lines
6.8 KiB
JavaScript
/* Adapted from echarts-doc by Apache ECharts
|
|
* https://github.com/apache/echarts-doc
|
|
* Licensed under the Apache-2.0 license
|
|
|
|
* url: https://github.com/apache/echarts-doc/blob/master/tool/schemaHelper.js
|
|
* License: https://github.com/apache/echarts-doc/blob/master/LICENSE
|
|
* @license
|
|
*/
|
|
|
|
function parseTypeValueOfArrayItem(schema, arrayItemKeys) {
|
|
const typeKey = arrayItemKeys.find(key => {
|
|
return !!(schema.properties && schema.properties[key] && schema.properties[key].default);
|
|
});
|
|
|
|
if (typeKey) {
|
|
return { key: typeKey, value: schema.properties[typeKey].default.replace(/'/g, '') };
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function traverse(schema, rootName, arrayItemKeys, cb) {
|
|
function innerTraverse(schemaNode, path, noCallback) {
|
|
if (!noCallback) {
|
|
cb(path, schemaNode);
|
|
}
|
|
|
|
if (schemaNode.items) {
|
|
if (schemaNode.items.anyOf) {
|
|
schemaNode.items.anyOf.forEach(itemSchema => {
|
|
let res = parseTypeValueOfArrayItem(itemSchema, arrayItemKeys);
|
|
if (res) {
|
|
innerTraverse(itemSchema, path ? path + '-' + res.value.replace(/'/g, '') : res.value, 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, arrayItemKeys) {
|
|
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);
|
|
const res = parseTypeValueOfArrayItem(schema, arrayItemKeys);
|
|
|
|
if (res) {
|
|
childNode.arrayItemType = res.value;
|
|
childNode.arrayItemTypeKey = res.key;
|
|
childNode.arrayParentType = parentNode.type;
|
|
} 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, arrayItemKeys) {
|
|
const keysRepeatCount = {};
|
|
const keysList = [];
|
|
traverse(schema, '', arrayItemKeys, (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, arrayItemKeys) {
|
|
let descriptionsMap = {};
|
|
let propWithUIControlCount = 0;
|
|
let propTotalCount = 0;
|
|
traverse(schema, docName, arrayItemKeys, (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('.');
|
|
|
|
// 支持三级展开页面
|
|
if (parts.length > 3) {
|
|
if (parts[1].includes('-') && parts[2].includes('-')) {
|
|
partionKey = `${parts[0]}.${parts[1]}-${parts[2].split('-')[1]}`;
|
|
subKey = parts.slice(3).join('.');
|
|
} else if (parts[2].includes('-')) {
|
|
partionKey = `${parts[0]}.${parts[1]}-${parts[2]}`;
|
|
subKey = parts.slice(3).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, {}, arrayItemKeys),
|
|
descriptions: descriptionsMap
|
|
};
|
|
};
|