flipper-plugin
Version:
Flipper Desktop plugin SDK and components
168 lines • 6.98 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TruncateHelper = exports.DataFormatter = void 0;
const icons_1 = require("@ant-design/icons");
const antd_1 = require("antd");
const lodash_1 = require("lodash");
const react_1 = __importStar(require("react"));
const urlRegex_1 = require("../utils/urlRegex");
const index_1 = require("../data-source/index");
const theme_1 = require("./theme");
const safeStringify_1 = require("../utils/safeStringify");
const FlipperLib_1 = require("../plugin/FlipperLib");
exports.DataFormatter = {
defaultFormatter(value, highlighter) {
if ((0, react_1.isValidElement)(value)) {
return value;
}
let res = '';
switch (typeof value) {
case 'boolean':
res = value ? 'true' : 'false';
break;
case 'number':
res = `${value}`;
break;
case 'undefined':
break;
case 'string':
res = value;
break;
case 'object': {
if (value === null)
break;
if (value instanceof Date) {
res = `${value.toTimeString().split(' ')[0]}.${(0, lodash_1.padStart)(`${value.getMilliseconds()}`, 3, '0')}`;
break;
}
if (value instanceof Map) {
res = (0, safeStringify_1.safeStringify)(Array.from(value.entries()));
break;
}
if (value instanceof Set) {
res = (0, safeStringify_1.safeStringify)(Array.from(value.values()));
break;
}
res = (0, safeStringify_1.safeStringify)(value);
break;
}
default:
res = '<unrenderable value>';
}
return highlighter?.render(res) ?? res;
},
truncate(maxLength) {
return (value, highlighter) => {
if (typeof value === 'string' && value.length > maxLength) {
return (react_1.default.createElement(TruncateHelper, { value: value, maxLength: maxLength, textWrapper: highlighter }));
}
return value;
};
},
/**
* Formatter that will automatically create links for any urls inside the data
*/
linkify(value) {
if (typeof value === 'string' && urlRegex_1.urlRegex.test(value)) {
return (0, react_1.createElement)(react_1.Fragment, undefined, value.split(urlRegex_1.urlRegex).map((part, index) =>
// odd items are the links
index % 2 === 1 ? (react_1.default.createElement(antd_1.Typography.Link, { key: index, href: part }, part)) : (part)));
}
return value;
},
prettyPrintJson(value) {
if ((0, react_1.isValidElement)(value)) {
return value;
}
if (typeof value === 'string' && value.length >= 2) {
const last = value.length - 1;
// kinda looks like json
if ((value[0] === '{' && value[last] === '}') ||
(value[0] === '[' && value[last] === ']')) {
try {
value = JSON.parse(value);
}
catch (e) {
// intentional fall through, can't parse this 'json'
}
}
}
if (typeof value === 'object' &&
value !== null &&
(Array.isArray(value) || (0, lodash_1.isPlainObject)(value))) {
try {
// Note: we don't need to be inserted <br/>'s in the output, but assume the text container uses
// white-space: pre-wrap (or pre)
return JSON.stringify(value, null, 2);
}
catch (e) {
// intentional fall through, can't pretty print this 'json'
}
}
return value;
},
format(value, formatters, highlighter) {
let res = value;
if (Array.isArray(formatters)) {
for (const formatter of formatters) {
res = formatter(res, highlighter);
}
}
else if (formatters) {
res = formatters(res, highlighter);
}
return exports.DataFormatter.defaultFormatter(res, highlighter);
},
};
// exported for testing
function TruncateHelper({ value, maxLength, textWrapper, }) {
const [collapsed, setCollapsed] = (0, react_1.useState)(true);
const redrawRow = (0, index_1.useTableRedraw)();
const message = collapsed ? value.substr(0, maxLength) : value;
return (react_1.default.createElement(react_1.default.Fragment, null,
textWrapper ? textWrapper.render(message) : message,
react_1.default.createElement(antd_1.Button, { onClick: () => {
setCollapsed((c) => !c);
redrawRow?.();
}, size: "small", type: "text", style: truncateButtonStyle, icon: collapsed ? react_1.default.createElement(icons_1.CaretRightOutlined, null) : react_1.default.createElement(icons_1.CaretUpOutlined, null) }, collapsed ? `and ${value.length - maxLength} more` : 'collapse'),
react_1.default.createElement(antd_1.Button, { icon: react_1.default.createElement(icons_1.CopyOutlined, null), onClick: () => {
(0, FlipperLib_1.tryGetFlipperLibImplementation)()?.writeTextToClipboard(value);
}, size: "small", type: "text", style: truncateButtonStyle }, "copy")));
}
exports.TruncateHelper = TruncateHelper;
const truncateButtonStyle = {
color: theme_1.theme.primaryColor,
marginLeft: 4,
};
//# sourceMappingURL=DataFormatter.js.map
;