UNPKG

slightning-coco-widget

Version:

SLIGHTNING 的 CoCo 控件框架。

380 lines (379 loc) 18 kB
import { capitalize, splitArray } from "../../utils"; import { traverseTypes } from "../decorators"; import { Color, MethodBlockParam } from "../types"; import { eventKeyMap } from "../utils"; export function convertToCoCo(types, widget) { return [typesToCoCo(types), new Proxy(widget, { construct(target, argArray, newTarget) { const [props] = argArray; const widgetInstance = Reflect.construct(target, argArray, newTarget); for (const [key, value] of Object.entries(props)) { Object.defineProperty(widgetInstance, key, { value, writable: true, enumerable: true, configurable: true }); } return widgetInstance; } })]; } export function typesToCoCo(types) { var _a, _b, _c, _d, _e, _f; const result = { type: types.type, title: types.info.title, icon: types.info.icon, version: (_a = types.info.version) !== null && _a !== void 0 ? _a : undefined, author: (_b = types.info.author) !== null && _b !== void 0 ? _b : undefined, docs: { url: (_d = (_c = types.info.url) === null || _c === void 0 ? void 0 : _c.docs) !== null && _d !== void 0 ? _d : undefined }, isInvisibleWidget: !types.options.visible, isGlobalWidget: types.options.global, platforms: (_e = types.options.platforms) !== null && _e !== void 0 ? _e : undefined, hasAnyWidget: (_f = types.options.any) !== null && _f !== void 0 ? _f : undefined, properties: [], methods: [], events: [] }; const labels = []; let showLine = false; let addSpace = false; let last = null; let count = 0; traverseTypes(types, { PropertyGroup: { enter(node) { if (node.value.label != null) { labels.push(node.value.label); showLine = true; } addSpace = true; }, exit(node) { if (node.value.label != null) { labels.pop(); showLine = true; } addSpace = true; } }, PropertyTypes(node) { var _a; if (addSpace) { if (last != null) { (_a = last.blockOptions) !== null && _a !== void 0 ? _a : (last.blockOptions = {}); last.blockOptions.space = 40; } addSpace = false; } result.properties.push(last = Object.assign(Object.assign({ key: node.value.key, label: node.value.label }, node.value.type.toCoCoPropertyValueTypes()), { blockOptions: { getter: { generateBlock: node.blockOptions.get != false }, setter: { generateBlock: node.blockOptions.set != false }, line: typeof showLine == "string" ? showLine : showLine ? labels.join("·") : undefined } })); showLine = false; }, MethodGroup: { enter(node) { if (node.value.label != null) { labels.push(node.value.label); showLine = true; } addSpace = true; }, exit(node) { if (node.value.label != null) { labels.pop(); showLine = true; } addSpace = true; } }, MethodTypes(node) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; if (addSpace) { if (last != null) { (_a = last.blockOptions) !== null && _a !== void 0 ? _a : (last.blockOptions = {}); last.blockOptions.space = 40; } addSpace = false; } const { value: method } = node; if (method.throws != null && !(method.throws.isVoid())) { throw new Error(`无法将方法 ${method.label} 的抛出类型转为 CoCo 类型`); } const deprecated = (_c = (_b = method.deprecated) !== null && _b !== void 0 ? _b : node.blockOptions.deprecated) !== null && _c !== void 0 ? _c : false; const transformed = Object.assign(Object.assign({ key: method.key, params: [] }, (_d = method.returns) === null || _d === void 0 ? void 0 : _d.toCoCoMethodValueTypes()), { tooltip: (_e = method.tooltip) !== null && _e !== void 0 ? _e : undefined, blockOptions: { callMethodLabel: false, line: typeof showLine == "string" ? showLine : showLine ? labels.join("·") : undefined, order: ++count, icon: (_f = node.blockOptions.icon) !== null && _f !== void 0 ? _f : undefined, color: deprecated ? Color.GREY : (_g = node.blockOptions.color) !== null && _g !== void 0 ? _g : undefined, inputsInline: (_h = node.blockOptions.inline) !== null && _h !== void 0 ? _h : undefined } }); if (typeof deprecated == "string") { if (transformed.tooltip == null) { transformed.tooltip = `${deprecated}`; } else { transformed.tooltip = `${deprecated}\n\n${transformed.tooltip}`; } } else if (deprecated) { if (transformed.tooltip == null) { transformed.tooltip = `该方法已弃用,并且可能在未来版本中移除,请尽快迁移到其他方法`; } else { transformed.tooltip = `该方法已弃用,并且可能在未来版本中移除,请尽快迁移到其他方法\n\n${transformed.tooltip}`; } } if (!method.block.includes(MethodBlockParam.THIS)) { throw new Error(`方法 ${method.label} 缺少 this 参数`); } (_j = transformed.blockOptions) !== null && _j !== void 0 ? _j : (transformed.blockOptions = {}); const inline = (_k = node.blockOptions.inline) !== null && _k !== void 0 ? _k : true; if (inline) { let restParts = null; let labelsBeforeThis = []; if (deprecated != false) { labelsBeforeThis.push("[已弃用]"); } for (let i = 0; i < method.block.length; i++) { const part = method.block[i]; if (part == MethodBlockParam.METHOD) { labelsBeforeThis.push(method.label); } else if (part == MethodBlockParam.BREAK_LINE) { labelsBeforeThis.push(""); } else if (part == MethodBlockParam.THIS) { restParts = method.block.slice(i + 1); break; } else if (typeof part == "string") { labelsBeforeThis.push(part); } else if (part != undefined) { throw new Error(`方法 ${method.label} 的积木 this 参数前存在他参数,不能将其转为 CoCo 类型`); } } if (restParts == null) { throw new Error(`方法 ${method.label} 缺少 this 参数`); } if (labelsBeforeThis.length != 0) { transformed.blockOptions.callMethodLabel = labelsBeforeThis.join(" "); } let lastParam = null; function addText(text) { if (lastParam == null) { if (transformed.label == null) { transformed.label = text; } else { transformed.label = `${transformed.label} ${text}`; } } else { if (lastParam.labelAfter == null) { lastParam.labelAfter = text; } else { lastParam.labelAfter = `${lastParam.labelAfter} ${text}`; } } } for (const part of restParts) { if (part == MethodBlockParam.THIS) { throw new Error(`方法只能有一个 this 参数,而方法 ${method.label} 有多个 this 参数`); } else if (part == MethodBlockParam.METHOD) { addText(method.label); } else if (typeof part == "string") { addText(part); } else { lastParam = Object.assign({ key: part.key }, part.type.toCoCoMethodParamValueTypes()); transformed.params.push(lastParam); } } } else { transformed.blockOptions.inputsInline = false; const blockLines = splitArray(method.block, MethodBlockParam.BREAK_LINE); if (!(() => { var _a, _b; const transformedParams = []; let labelsBeforeThis = []; let afterThis = false; let labelsAfterThis = []; let positionAfterThis = 1; for (const item of (_a = blockLines[0]) !== null && _a !== void 0 ? _a : []) { if (item == MethodBlockParam.THIS) { if (afterThis) { throw new Error(`方法只能有一个 this 参数,而方法 ${method.label} 有多个 this 参数`); } else { afterThis = true; } } else if (afterThis) { return false; } else if (typeof item == "string") { const text = item == MethodBlockParam.METHOD ? method.label : item; labelsBeforeThis.push(text); } else { throw new Error(`方法 ${method.label} 的积木 this 参数前存在他参数,不能将其转为 CoCo 类型`); } } if (!afterThis) { throw new Error(`方法 ${method.label} 的积木 this 参数前存在他参数,不能将其转为 CoCo 类型`); } if ((_b = blockLines[1]) === null || _b === void 0 ? void 0 : _b.every((item) => typeof item == "string")) { positionAfterThis = 2; for (const item of blockLines[1]) { const text = item == MethodBlockParam.METHOD ? method.label : item; labelsAfterThis.push(text); } } let lastTransformedParam = null; for (const line of blockLines.slice(positionAfterThis)) { let labels = []; let param = null; for (const item of line) { if (item == MethodBlockParam.THIS) { throw new Error(`方法只能有一个 this 参数,而方法 ${method.label} 有多个 this 参数`); } else if (typeof item == "string") { if (param != null) { return false; } const text = item == MethodBlockParam.METHOD ? method.label : item; labels.push(text); } else if (param == null) { param = item; } else { return false; } } if (param != null) { lastTransformedParam = Object.assign({ key: param.key, label: labels.join(" ") }, param.type.toCoCoMethodParamValueTypes()); transformedParams.push(lastTransformedParam); } else if (lastTransformedParam != null) { lastTransformedParam.labelAfter = labels.join(" "); lastTransformedParam = null; } else { return false; } } if (labelsBeforeThis.length != 0) { transformed.blockOptions.callMethodLabel = labelsBeforeThis.join(" "); } transformed.label = labelsAfterThis.join(" "); transformed.params = transformedParams; return true; })()) { transformed.label = method.label; for (const part of method.block) { if (typeof part != "object") { continue; } transformed.params.push(Object.assign({ key: part.key, label: part.label }, part.type.toCoCoMethodParamValueTypes())); } } if (deprecated != false) { transformed.blockOptions.callMethodLabel = `[已弃用] ${transformed.blockOptions.callMethodLabel || ""}`; } } showLine = false; last = transformed; result.methods.push(transformed); }, EventTypes(node) { var _a, _b, _c, _d, _e, _f; if (addSpace) { if (last != null) { (_a = last.blockOptions) !== null && _a !== void 0 ? _a : (last.blockOptions = {}); last.blockOptions.space = 40; } addSpace = false; } const deprecated = (_c = (_b = node.value.deprecated) !== null && _b !== void 0 ? _b : node.blockOptions.deprecated) !== null && _c !== void 0 ? _c : false; const transformed = { key: node.value.key, subTypes: (_d = node.value.subTypes) !== null && _d !== void 0 ? _d : undefined, label: deprecated != false ? `[已弃用] ${node.value.label}` : node.value.label, params: node.value.params.map((param) => { return Object.assign({ key: param.key, label: param.label }, param.type.toCoCoEventParamValueTypes()); }), tooltip: (_e = node.value.tooltip) !== null && _e !== void 0 ? _e : undefined, blockOptions: { line: typeof showLine == "string" ? showLine : showLine ? labels.join("·") : undefined, order: ++count, icon: (_f = node.blockOptions.icon) !== null && _f !== void 0 ? _f : undefined } }; if (node.value.subTypes != null) { addEventSubTypesMap(node.value.subTypes, 0, [node.value.key], [node.value.key], [node.value.label], node.value); } if (typeof deprecated == "string") { if (transformed.tooltip == null) { transformed.tooltip = `${deprecated}`; } else { transformed.tooltip = `${deprecated}\n\n${transformed.tooltip}`; } } else if (deprecated) { if (transformed.tooltip == null) { transformed.tooltip = `该事件已弃用,并且可能在未来版本中移除,请尽快迁移到其他事件`; } else { transformed.tooltip = `该事件已弃用,并且可能在未来版本中移除,请尽快迁移到其他事件\n\n${transformed.tooltip}`; } } showLine = false; last = transformed; result.events.push(transformed); }, BlockBoxOptions(node) { var _a; if (node.value.space != null && last != null) { (_a = last.blockOptions) !== null && _a !== void 0 ? _a : (last.blockOptions = {}); last.blockOptions.space = node.value.space; } if (node.value.line != null) { showLine = node.value.line; } } }); return result; } function addEventSubTypesMap(subTypes, i, keys, capitalizedKeys, labels, event) { if (i >= subTypes.length) { eventKeyMap[capitalizedKeys.join("")] = keys.join(""); return; } const subType = subTypes[i]; if (subType == undefined) { addEventSubTypesMap(subTypes, i + 1, keys, capitalizedKeys, labels, event); return; } for (const item of subType.dropdown) { addEventSubTypesMap(subTypes, i + 1, [...keys, item.value], [...capitalizedKeys, capitalize(item.value)], [...labels, item.label], event); } }