return acc; }, []); // Render array of React spans renderElements = tinyElementsRender; } else { // Elements Default case renderElements = getElements(props); } return span(config, ...renderElements, inspectIcon ? inspectIcon : null); } function getElementConfig(opts) { const { object, isInTree, onDOMNodeClick, onDOMNodeMouseOver, onDOMNodeMouseOut, shouldRenderTooltip, tooltipString, } = opts; // Initiate config const config = { "data-link-actor-id": object.actor, "data-link-content-dom-reference": JSON.stringify( object.contentDomReference ), className: "objectBox objectBox-node", }; // Triage event handlers if (isInTree) { if (onDOMNodeClick) { Object.assign(config, { onClick: _ => onDOMNodeClick(object), className: `${config.className} clickable`, }); } if (onDOMNodeMouseOver) { Object.assign(config, { onMouseOver: _ => onDOMNodeMouseOver(object), }); } if (onDOMNodeMouseOut) { Object.assign(config, { onMouseOut: _ => onDOMNodeMouseOut(object), }); } } // If tooltip, build tooltip if (tooltipString && shouldRenderTooltip) { config.title = tooltipString; } // Return config obj return config; } function getElements(opts) { const { object: grip } = opts; const { attributes, nodeName } = grip.preview; const nodeNameElement = span( { className: appendRTLClassNameIfNeeded("tag-name", nodeName), }, nodeName ); const attributeKeys = Object.keys(attributes); if (attributeKeys.includes("class")) { attributeKeys.splice(attributeKeys.indexOf("class"), 1); attributeKeys.unshift("class"); } if (attributeKeys.includes("id")) { attributeKeys.splice(attributeKeys.indexOf("id"), 1); attributeKeys.unshift("id"); } const attributeElements = attributeKeys.reduce((arr, name) => { const value = attributes[name]; let title = isLongString(value) ? value.initial : value; if (title.length < MAX_ATTRIBUTE_LENGTH) { title = null; } const attribute = span( {}, span( { className: appendRTLClassNameIfNeeded("attrName", name), }, name ), span({ className: "attrEqual" }, "="), StringRep({ className: "attrValue", object: value, cropLimit: MAX_ATTRIBUTE_LENGTH, title, }) ); return arr.concat([" ", attribute]); }, []); return [ span({ className: "angleBracket" }, "<"), nodeNameElement, ...attributeElements, span({ className: "angleBracket" }, ">"), ]; } function getTinyElements(grip) { const { attributes, nodeName } = grip.preview; // Initialize elements array const elements = [ { config: { className: appendRTLClassNameIfNeeded("tag-name", nodeName), }, content: nodeName, }, ]; // Push ID element if (attributes.id) { elements.push({ config: { className: appendRTLClassNameIfNeeded("attrName", attributes.id), }, content: `#${attributes.id}`, }); } // Push Classes if (attributes.class) { const elementClasses = attributes.class .trim() .split(/\s+/) .map(cls => `.${cls}`) .join(""); elements.push({ config: { className: appendRTLClassNameIfNeeded("attrName", elementClasses), }, content: elementClasses, }); } return elements; } function getInspectIcon(opts) { const { object, isInTree, onInspectIconClick, inspectIconTitle, inspectIconClassName, onDOMNodeClick, } = opts; if (!isInTree || !onInspectIconClick) { return null; } return button({ className: inspectIconClassName || "open-inspector", // TODO: Localize this with "openNodeInInspector" when Bug 1317038 lands title: inspectIconTitle || "Click to select the node in the inspector", onClick: e => { if (onDOMNodeClick) { e.stopPropagation(); } onInspectIconClick(object, e); }, }); } // Registration function supportsObject(object) { return object?.preview?.nodeType === nodeConstants.ELEMENT_NODE; } const rep = wrapRender(ElementNode); // Exports from this module export { rep, supportsObject, MAX_ATTRIBUTE_LENGTH }; PK