+{"source":"/src/components/tools/lively-ast-explorer-example-source.js","plugin":"https://lively-kernel.org/lively4/lively4-tom/src/components/tools/babel-plugin-explorer-playground.js","options":{"autoUpdateAST":true,"autoUpdateTransformation":true,"autoExecute":true,"systemJS":false,"autoRunTests":false,"autoSaveWorkspace":false},"pluginSelection":[{"url":"https://lively-kernel.org/lively4/lively4-tom/src/external/babel-plugin-syntax-function-bind.js","name":"babel-plugin-syntax-function-bind.js","size":"149","modified":"2020-11-08 20:33:44","version":"cf788e085403d48c22bb7a2e2bdb67be0968fcb1","content":"export default function () {\r\n return {\r\n manipulateOptions(opts, parserOpts) {\r\n parserOpts.plugins.push(\"functionBind\");\r\n }\r\n };\r\n}\r\n","type":"file","title":"export default function () {\r","tags":[],"unboundIdentifiers":["manipulateOptions","plugins","push"]},{"url":"https://lively-kernel.org/lively4/lively4-tom/src/client/reactive/reactive-jsx/babel-plugin-jsx-lively.js","name":"babel-plugin-jsx-lively.js","size":"7640","modified":"2020-11-08 20:33:44","version":"ab4c0473f913da10ed34169b50b78eb1c2190928","content":"import jsx from \"babel-plugin-syntax-jsx\";\nimport Preferences from 'src/client/preferences.js';\n\nfunction detectUnsupportedNodes(path, filename) {\n function gainPrintableFullPath(path) {\n let fullPath = [];\n\n while (path) {\n fullPath.unshift(path.node.type);\n path = path.parentPath;\n }\n\n return fullPath.map((nodeType, index) => ' '.repeat(index) + nodeType).join('\\n');\n }\n\n path.traverse({\n /**\n * No support for JSXMemberExpression yet. #TODO: what are the semantics outside of react for this?\n * \n * <foo.bar></foo.bar>\n */\n JSXMemberExpression(path, state) {\n throw new SyntaxError(`JSXMemberExpression not yet supported.\n${gainPrintableFullPath(path)}`, filename, path.node.loc.start.line);\n },\n /**\n * No support for JSXEmptyExpression yet. #TODO: where is this feature even useful?\n * \n * <div id={}></div>\n * or\n * <div>{}</div>\n */\n JSXEmptyExpression(path, state) {\n throw new SyntaxError(`JSXEmptyExpression not yet supported.\n${gainPrintableFullPath(path)}`, filename);\n },\n /**\n * No support for jSXNamespacedName yet.\n * \n * <div ns:attr=\"val\" />;\n */\n JSXNamespacedName(path, state) {\n throw new SyntaxError(`jSXNamespacedName not yet supported.\n${gainPrintableFullPath(path)}`, filename, path.node.loc.start.line);\n }\n });\n}\n\n/**\n * Resources for JSX Syntax\n * JSX babel Preset: https://github.com/babel/babel/blob/master/packages/babel-preset-react/src/index.js\n * JSX spec draft: https://github.com/facebook/jsx\n * JSX Syntax definition in babel: https://github.com/babel/babel/blob/master/packages/babel-types/src/definitions/jsx.js#L10\n * Babel nodes list: https://babeljs.io/docs/core-packages/babel-types/#apij-sxidentifier\n */\nexport default function ({ types: t, template, traverse }) {\n const GENERATED_IMPORT_IDENTIFIER = Symbol(\"generated import identifier\");\n\n // #TODO: duplicate with aexpr transform -> extract it\n function addCustomTemplate(file, name) {\n let declar = file.declarations[name];\n if (declar) return declar;\n\n let identifier = file.declarations[name] = file.addImport(\"reactive-jsx\", name, name);\n identifier[GENERATED_IMPORT_IDENTIFIER] = true;\n return identifier;\n }\n\n return {\n inherits: jsx,\n visitor: {\n Program(path, state) {\n detectUnsupportedNodes(path, state && state.opts && state.opts.filename);\n\n const fileName = state && state.file && state.file.log && state.file.log.filename || 'no_file_given';\n const sourceLocation = template(`({\n file: '${fileName}',\n end: {\n column: END_COLUMN,\n line: END_LINE\n },\n start: {\n column: START_COLUMN,\n line: START_LINE\n }\n })`);\n function buildSourceLocation(node) {\n return sourceLocation({\n END_COLUMN: t.numericLiteral(node.loc.end.column),\n END_LINE: t.numericLiteral(node.loc.end.line),\n START_COLUMN: t.numericLiteral(node.loc.start.column),\n START_LINE: t.numericLiteral(node.loc.start.line)\n }).expression;\n }\n\n function transformPath(path, programState) {\n function jSXAttributeToBuilder(path) {\n\n function getCallExpressionFor(functionName, ...additionalParameters) {\n return t.callExpression(addCustomTemplate(programState.file, functionName), // builder function\n [t.stringLiteral(path.get(\"name\").node.name), // key\n ...additionalParameters]);\n }\n\n let attributeValue = path.get(\"value\");\n if (path.isJSXSpreadAttribute()) {\n return t.callExpression(addCustomTemplate(programState.file, \"attributeSpread\"), [path.get(\"argument\").node]);\n } else if (!path.node.value) {\n return getCallExpressionFor(\"attributeEmpty\");\n } else if (attributeValue.isStringLiteral()) {\n return getCallExpressionFor(\"attributeStringLiteral\", attributeValue.node);\n } else if (attributeValue.isJSXExpressionContainer()) {\n return getCallExpressionFor(\"attributeExpression\", attributeValue.node.expression);\n } else if (attributeValue.isJSXElement()) {\n // #TODO: what would that even mean?\n throw new SyntaxError(`JSXElement as property value of JSXAttribute not yet supported.`);\n }\n\n throw new Error('unknown node type in JSXAttribute value ' + attributeValue.node.type);\n }\n\n function jSXChildrenToBuilder(child) {\n function getCallExpressionFor(functionName, childSpec) {\n return t.callExpression(addCustomTemplate(programState.file, functionName), // builder function\n [childSpec]);\n }\n\n if (child.isJSXText()) {\n return getCallExpressionFor(\"childText\", t.stringLiteral(child.node.value));\n }\n if (child.isJSXElement()) {\n return getCallExpressionFor(\"childElement\", child.node);\n }\n if (child.isJSXExpressionContainer()) {\n return getCallExpressionFor(\"childExpression\", child.get(\"expression\").node);\n }\n if (child.isJSXSpreadChild()) {\n return getCallExpressionFor(\"childSpread\", child.get(\"expression\").node);\n //throw new SyntaxError(`JSXSpreadChild as child of JSXElement not yet supported.`);\n }\n throw new Error('unknown node type in children of JSXElement ' + child.node.type);\n }\n\n path.traverse({\n JSXElement(path, state) {\n const jSXAttributes = path.get(\"openingElement\").get(\"attributes\");\n const jSXChildren = path.get(\"children\");\n\n let newNode = t.callExpression(addCustomTemplate(programState.file, \"element\"), [t.stringLiteral(path.get(\"openingElement\").get(\"name\").node.name), t.callExpression(addCustomTemplate(programState.file, \"attributes\"), jSXAttributes.map(jSXAttributeToBuilder)), t.callExpression(addCustomTemplate(programState.file, \"children\"), jSXChildren.map(jSXChildrenToBuilder)), buildSourceLocation(path.node)]);\n\n path.replaceWith(newNode);\n },\n CallExpression(path) {\n if (path.node.__wrappedInMetaInformation__) {\n return;\n }\n path.node.__wrappedInMetaInformation__ = true;\n\n function isDomCreatingCall(path) {\n const callee = path.get('callee');\n if (!callee.isMemberExpression() || callee.node.computed) {\n return false;\n }\n\n const object = callee.get('object');\n const property = callee.get('property');\n\n if (!object.isIdentifier()) {\n return false;\n }\n if (!property.isIdentifier()) {\n return false;\n }\n\n const livelyCreate = object.node.name === 'lively' && property.node.name === 'create';\n const documentCreateElement = object.node.name === 'document' && property.node.name === 'createElement';\n return livelyCreate || documentCreateElement;\n }\n\n if (isDomCreatingCall(path)) {\n path.replaceWith(t.callExpression(addCustomTemplate(programState.file, \"addSourceLocation\"), [path.node, buildSourceLocation(path.node)]));\n }\n }\n });\n\n return path;\n }\n\n transformPath(path, state);\n }\n }\n };\n}","type":"file","title":"import jsx from \"babel-plugin-syntax-jsx\";","tags":[],"unboundIdentifiers":["unshift","node","type","parentPath","map","repeat","join","traverse","JSXMemberExpression","SyntaxError","loc","start","line","JSXEmptyExpression","JSXNamespacedName","types","Symbol","declarations","addImport","inherits","visitor","Program","opts","filename","file","log","END_COLUMN","numericLiteral","end","column","END_LINE","START_COLUMN","START_LINE","expression","callExpression","stringLiteral","get","name","isJSXSpreadAttribute","value","isStringLiteral","isJSXExpressionContainer","isJSXElement","Error","isJSXText","isJSXSpreadChild","JSXElement","replaceWith","CallExpression","__wrappedInMetaInformation__","isMemberExpression","computed","isIdentifier"]}]}
0 commit comments