marko
Version:
UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.
128 lines (106 loc) • 4 kB
JavaScript
;exports.__esModule = true;exports.default = _default;var _compiler = require("@marko/compiler");
var _babelUtils = require("@marko/compiler/babel-utils");
var _withPreviousLocation = _interopRequireDefault(require("../util/with-previous-location"));
var _dynamicTag = _interopRequireDefault(require("./dynamic-tag"));
var _nativeTag = _interopRequireDefault(require("./native-tag"));
var _util = require("./util");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
function _default(path, isNullable) {
const {
hub: { file },
node
} = path;
const { markoOpts } = file;
const { name, key } = node;
(0, _babelUtils.assertNoArgs)(path);
let tagIdentifier;
if (node.extra?.featureType === "tags") {
path.set(
"name",
path.scope.hasBinding(name.value) ?
_compiler.types.identifier(name.value) :
(0, _babelUtils.importDefault)(file, node.extra.relativePath, name.value)
);
return (0, _dynamicTag.default)(path);
}
if (_compiler.types.isStringLiteral(name)) {
const tagName = name.value;
let relativePath = node.extra && node.extra.relativePath;
if (!relativePath) {
const tagDef = (0, _babelUtils.getTagDef)(path);
if (tagDef && tagDef.renderer) {
// Normally new tags should not be added in the translate stage.
// We make an exception here for core tags, init-components & _preserve being the primary culprits.
// TODO: in the future refactor so this is not needed.
relativePath = (0, _babelUtils.resolveRelativePath)(file, tagDef.renderer);
}
}
let binding = !relativePath && path.scope.getBinding(tagName);
if (binding && !binding.identifier.loc) binding = null;
if (relativePath) {
tagIdentifier = (0, _babelUtils.importDefault)(file, relativePath, tagName);
} else if (binding) {
path.set("name", _compiler.types.identifier(tagName));
return (0, _dynamicTag.default)(path);
} else if (markoOpts.ignoreUnrecognizedTags) {
return (0, _nativeTag.default)(path);
} else {
throw path.
get("name").
buildCodeFrameError(
`Unable to find entry point for custom tag <${tagName}>.`
);
}
} else {
tagIdentifier = name;
}
const foundAttrs = (0, _util.getAttrs)(path);
const customTagRenderCall = (0, _withPreviousLocation.default)(
_compiler.types.expressionStatement(
_compiler.types.callExpression(
(0, _babelUtils.importDefault)(
file,
"marko/src/runtime/helpers/render-tag.js",
"marko_tag"
),
[
tagIdentifier,
// TODO: this could be left as null if we froze input mutations and used a default object in the runtime.
_compiler.types.isNullLiteral(foundAttrs) ? _compiler.types.objectExpression([]) : foundAttrs,
_compiler.types.identifier("out"),
file._componentDefIdentifier,
key,
...(0, _util.buildEventHandlerArray)(path)]
)
),
node
);
if (isNullable) {
let renderBodyIdentifier;
const renderBodyProp =
_compiler.types.isObjectExpression(foundAttrs) &&
foundAttrs.properties.find(
(prop) => prop.key && prop.key.value === "renderBody"
);
if (renderBodyProp) {
renderBodyIdentifier = path.scope.generateUidIdentifier("renderBody");
path.insertBefore(
_compiler.types.variableDeclaration("const", [
_compiler.types.variableDeclarator(renderBodyIdentifier, renderBodyProp.value)]
)
);
renderBodyProp.value = renderBodyIdentifier;
}
path.replaceWith(
_compiler.types.ifStatement(
name,
customTagRenderCall,
renderBodyIdentifier &&
_compiler.types.expressionStatement(
_compiler.types.callExpression(renderBodyIdentifier, [_compiler.types.identifier("out")])
)
)
);
} else {
path.replaceWith(customTagRenderCall);
}
}