react-json-editor-ajrm-ts-platform
Version:
A stylish, editor-like, modular, react component for viewing, editing, and debugging javascript object syntax!
1,035 lines (1,034 loc) • 94.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
// @ts-nocheck
const react_1 = tslib_1.__importStar(require("react"));
const themes_1 = tslib_1.__importDefault(require("./themes"));
const mitsuketa_1 = require("./mitsuketa");
const err_1 = tslib_1.__importDefault(require("./err"));
const locale_1 = require("./locale");
const en_1 = tslib_1.__importDefault(require("./locale/en"));
class JSONInput extends react_1.Component {
constructor(props) {
super(props);
this.mappedKeys = new Set();
this.updateInternalProps = this.updateInternalProps.bind(this);
this.createMarkup = this.createMarkup.bind(this);
this.onClick = this.onClick.bind(this);
this.onBlur = this.onBlur.bind(this);
this.update = this.update.bind(this);
this.getCursorPosition = this.getCursorPosition.bind(this);
this.setCursorPosition = this.setCursorPosition.bind(this);
this.scheduledUpdate = this.scheduledUpdate.bind(this);
this.setUpdateTime = this.setUpdateTime.bind(this);
this.renderLabels = this.renderLabels.bind(this);
this.newSpan = this.newSpan.bind(this);
this.renderErrorMessage = this.renderErrorMessage.bind(this);
this.onScroll = this.onScroll.bind(this);
this.showPlaceholder = this.showPlaceholder.bind(this);
this.tokenize = this.tokenize.bind(this);
this.onKeyPress = this.onKeyPress.bind(this);
this.onKeyDown = this.onKeyDown.bind(this);
this.onPaste = this.onPaste.bind(this);
this.stopEvent = this.stopEvent.bind(this);
this.refContent = null;
this.refLabels = null;
this.updateInternalProps();
this.renderCount = 1;
this.state = {
prevPlaceholder: "",
markupText: "",
plainText: "",
json: "",
jsObject: undefined,
lines: 0,
error: false,
isLoading: false,
};
if (!this.props.locale) {
console.warn("[react-json-editor-ajrm - Deprecation Warning] You did not provide a 'locale' prop for your JSON input - This will be required in a future version. English has been set as a default.");
}
}
updateInternalProps() {
let colors = {}, style = {}, theme = themes_1.default.dark_vscode_tribute;
if ("theme" in this.props)
if (typeof this.props.theme === "string")
if (this.props.theme in themes_1.default)
theme = themes_1.default[this.props.theme];
colors = theme;
if ("colors" in this.props)
colors = {
default: "default" in this.props.colors
? this.props.colors.default
: colors.default,
string: "string" in this.props.colors
? this.props.colors.string
: colors.string,
number: "number" in this.props.colors
? this.props.colors.number
: colors.number,
colon: "colon" in this.props.colors ? this.props.colors.colon : colors.colon,
keys: "keys" in this.props.colors ? this.props.colors.keys : colors.keys,
keys_whiteSpace: "keys_whiteSpace" in this.props.colors
? this.props.colors.keys_whiteSpace
: colors.keys_whiteSpace,
primitive: "primitive" in this.props.colors
? this.props.colors.primitive
: colors.primitive,
error: "error" in this.props.colors ? this.props.colors.error : colors.error,
background: "background" in this.props.colors
? this.props.colors.background
: colors.background,
background_warning: "background_warning" in this.props.colors
? this.props.colors.background_warning
: colors.background_warning,
};
this.colors = colors;
if ("style" in this.props)
style = {
outerBox: "outerBox" in this.props.style ? this.props.style.outerBox : {},
container: "container" in this.props.style ? this.props.style.container : {},
warningBox: "warningBox" in this.props.style ? this.props.style.warningBox : {},
errorMessage: "errorMessage" in this.props.style
? this.props.style.errorMessage
: {},
body: "body" in this.props.style ? this.props.style.body : {},
labelColumn: "labelColumn" in this.props.style ? this.props.style.labelColumn : {},
labels: "labels" in this.props.style ? this.props.style.labels : {},
contentBox: "contentBox" in this.props.style ? this.props.style.contentBox : {},
};
else
style = {
outerBox: {},
container: {},
warningBox: {},
errorMessage: {},
body: {},
labelColumn: {},
labels: {},
contentBox: {},
};
this.style = style;
this.confirmGood =
"confirmGood" in this.props ? this.props.confirmGood : true;
const totalHeight = this.props.height || "610px", totalWidth = this.props.width || "479px";
this.totalHeight = totalHeight;
this.totalWidth = totalWidth;
if (!("onKeyPressUpdate" in this.props) || this.props.onKeyPressUpdate) {
if (!this.timer)
this.timer = setInterval(this.scheduledUpdate, 100);
}
else if (this.timer) {
clearInterval(this.timer);
this.timer = false;
}
this.waitAfterKeyPress =
"waitAfterKeyPress" in this.props ? this.props.waitAfterKeyPress : 1000;
this.updateTime = false;
this.resetConfiguration = "reset" in this.props ? this.props.reset : false;
}
render() {
const id = this.props.id, markupText = this.state.markupText, error = this.props.error || this.state.error, colors = this.colors, style = this.style || {}, confirmGood = this.confirmGood, totalHeight = this.totalHeight, totalWidth = this.totalWidth, isLoading = this.state.isLoading, hasError = !!this.props.error || (error ? "token" in error : false);
this.renderCount++;
return (react_1.default.createElement("div", { id: id && id + "-outer-box", style: Object.assign({ display: "block", overflow: "none", height: totalHeight, width: totalWidth, margin: 0, boxSizing: "border-box", position: "relative" }, style.outerBox) },
confirmGood ? (react_1.default.createElement("div", { style: {
opacity: hasError ? 0 : 1,
height: "30px",
width: "30px",
position: "absolute",
top: 0,
right: 0,
transform: "translate(-25%,25%)",
pointerEvents: "none",
transitionDuration: "0.2s",
transitionTimingFunction: "cubic-bezier(0, 1, 0.5, 1)",
} }, isLoading
? react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", width: "30px", height: "30px", viewBox: "0 0 30 30", version: "1.1" },
react_1.default.createElement("g", { id: "surface1" },
react_1.default.createElement("path", { d: "M 8.863281 15 C 8.863281 14.246094 8.253906 13.636719 7.5 13.636719 L 2.046875 13.636719 C 1.292969 13.636719 0.683594 14.246094 0.683594 15 C 0.683594 15.753906 1.292969 16.363281 2.046875 16.363281 L 7.5 16.363281 C 8.253906 16.363281 8.863281 15.753906 8.863281 15 Z M 8.863281 15 " }),
react_1.default.createElement("path", { d: "M 27.953125 13.636719 L 25.226562 13.636719 C 24.472656 13.636719 23.863281 14.246094 23.863281 15 C 23.863281 15.753906 24.472656 16.363281 25.226562 16.363281 L 27.953125 16.363281 C 28.707031 16.363281 29.316406 15.753906 29.316406 15 C 29.316406 14.246094 28.707031 13.636719 27.953125 13.636719 Z M 27.953125 13.636719 " }),
react_1.default.createElement("path", { d: "M 15.683594 8.183594 C 16.433594 8.183594 17.046875 7.570312 17.046875 6.816406 L 17.046875 1.363281 C 17.046875 0.609375 16.433594 0 15.683594 0 C 14.929688 0 14.316406 0.609375 14.316406 1.363281 L 14.316406 6.816406 C 14.316406 7.570312 14.929688 8.183594 15.683594 8.183594 Z M 15.683594 8.183594 " }),
react_1.default.createElement("path", { d: "M 15.683594 21.816406 C 14.929688 21.816406 14.316406 22.429688 14.316406 23.183594 L 14.316406 28.636719 C 14.316406 29.390625 14.929688 30 15.683594 30 C 16.433594 30 17.046875 29.390625 17.046875 28.636719 L 17.046875 23.183594 C 17.046875 22.429688 16.433594 21.816406 15.683594 21.816406 Z M 15.683594 21.816406 " }),
react_1.default.createElement("path", { d: "M 7.003906 4.394531 C 6.472656 3.859375 5.609375 3.859375 5.074219 4.394531 C 4.542969 4.925781 4.542969 5.789062 5.074219 6.320312 L 8.933594 10.179688 C 9.199219 10.445312 9.546875 10.578125 9.894531 10.578125 C 10.246094 10.578125 10.59375 10.445312 10.859375 10.179688 C 11.394531 9.644531 11.394531 8.78125 10.859375 8.25 Z M 7.003906 4.394531 " }),
react_1.default.createElement("path", { d: "M 22.429688 19.820312 C 21.898438 19.289062 21.035156 19.289062 20.503906 19.820312 C 19.96875 20.355469 19.96875 21.21875 20.503906 21.75 L 24.359375 25.605469 C 24.625 25.871094 24.976562 26.007812 25.324219 26.007812 C 25.671875 26.007812 26.023438 25.871094 26.289062 25.605469 C 26.820312 25.074219 26.820312 24.210938 26.289062 23.679688 Z M 22.429688 19.820312 " }),
react_1.default.createElement("path", { d: "M 8.933594 19.820312 L 5.074219 23.679688 C 4.542969 24.210938 4.542969 25.074219 5.074219 25.605469 C 5.339844 25.871094 5.691406 26.007812 6.039062 26.007812 C 6.386719 26.007812 6.738281 25.871094 7.003906 25.605469 L 10.859375 21.75 C 11.394531 21.21875 11.394531 20.355469 10.859375 19.820312 C 10.328125 19.289062 9.464844 19.289062 8.933594 19.820312 Z M 8.933594 19.820312 " })))
: react_1.default.createElement("svg", { height: "30px", width: "30px", viewBox: "0 0 100 100" },
react_1.default.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", fill: "green", opacity: "0.85", d: "M39.363,79L16,55.49l11.347-11.419L39.694,56.49L72.983,23L84,34.085L39.363,79z" })))) : (void 0),
react_1.default.createElement("div", { id: id && id + "-container", style: Object.assign({ display: "block", height: totalHeight, width: totalWidth, margin: 0, boxSizing: "border-box", overflow: "hidden", fontFamily: "Roboto, sans-serif" }, style.container), onClick: this.onClick },
react_1.default.createElement("div", { id: id && id + "-warning-box", style: Object.assign({ display: "block", overflow: "hidden", height: hasError ? "60px" : "0px", width: "100%", margin: 0, backgroundColor: colors.background_warning, transitionDuration: "0.2s", transitionTimingFunction: "cubic-bezier(0, 1, 0.5, 1)" }, style.warningBox), onClick: this.onClick },
react_1.default.createElement("span", { style: {
display: "inline-block",
height: "60px",
width: "60px",
margin: 0,
boxSizing: "border-box",
overflow: "hidden",
verticalAlign: "top",
pointerEvents: "none",
}, onClick: this.onClick },
react_1.default.createElement("div", { style: {
position: "relative",
top: 0,
left: 0,
height: "60px",
width: "60px",
margin: 0,
pointerEvents: "none",
}, onClick: this.onClick },
react_1.default.createElement("div", { style: {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
pointerEvents: "none",
}, onClick: this.onClick },
react_1.default.createElement("svg", { height: "25px", width: "25px", viewBox: "0 0 100 100" },
react_1.default.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", fill: "red", d: "M73.9,5.75c0.467-0.467,1.067-0.7,1.8-0.7c0.7,0,1.283,0.233,1.75,0.7l16.8,16.8 c0.467,0.5,0.7,1.084,0.7,1.75c0,0.733-0.233,1.334-0.7,1.801L70.35,50l23.9,23.95c0.5,0.467,0.75,1.066,0.75,1.8 c0,0.667-0.25,1.25-0.75,1.75l-16.8,16.75c-0.534,0.467-1.117,0.7-1.75,0.7s-1.233-0.233-1.8-0.7L50,70.351L26.1,94.25 c-0.567,0.467-1.167,0.7-1.8,0.7c-0.667,0-1.283-0.233-1.85-0.7L5.75,77.5C5.25,77,5,76.417,5,75.75c0-0.733,0.25-1.333,0.75-1.8 L29.65,50L5.75,26.101C5.25,25.667,5,25.066,5,24.3c0-0.666,0.25-1.25,0.75-1.75l16.8-16.8c0.467-0.467,1.05-0.7,1.75-0.7 c0.733,0,1.333,0.233,1.8,0.7L50,29.65L73.9,5.75z" }))))),
react_1.default.createElement("span", { style: {
display: "inline-block",
height: "60px",
width: "calc(100% - 60px)",
margin: 0,
overflow: "hidden",
verticalAlign: "top",
position: "absolute",
pointerEvents: "none",
}, onClick: this.onClick }, this.renderErrorMessage())),
react_1.default.createElement("div", { id: id && id + "-body", style: Object.assign({ display: "flex", overflow: "none", height: hasError ? "calc(100% - 60px)" : "100%", width: "", margin: 0, resize: "none", fontFamily: "Roboto Mono, Monaco, monospace", fontSize: "11px", backgroundColor: colors.background, transitionDuration: "0.2s", transitionTimingFunction: "cubic-bezier(0, 1, 0.5, 1)" }, style.body), onClick: this.onClick },
react_1.default.createElement("span", { id: id && id + "-labels", ref: (ref) => (this.refLabels = ref), style: Object.assign({ display: "inline-block", boxSizing: "border-box", verticalAlign: "top", height: "100%", width: "44px", margin: 0, padding: "5px 0px 5px 10px", overflow: "hidden", color: "#D4D4D4" }, style.labelColumn), onClick: this.onClick }, this.renderLabels()),
react_1.default.createElement("span", { id: id, ref: (ref) => (this.refContent = ref), contentEditable: true, style: Object.assign({ display: "inline-block", boxSizing: "border-box", verticalAlign: "top", height: "100%", width: "", flex: 1, margin: 0, padding: "5px", overflowX: "hidden", overflowY: "auto", wordWrap: "break-word", whiteSpace: "pre-line", color: "#D4D4D4", outline: "none" }, style.contentBox), dangerouslySetInnerHTML: this.createMarkup(markupText), onKeyPress: this.onKeyPress, onKeyDown: this.onKeyDown, onClick: this.onClick, onBlur: this.onBlur, onScroll: this.onScroll, onPaste: this.onPaste,
// @ts-ignore
autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false })))));
}
renderErrorMessage() {
const locale = this.props.locale || en_1.default, error = this.props.error || this.state.error, style = this.style;
if (!error)
return void 0;
return (react_1.default.createElement("p", { style: Object.assign({ color: "red", fontSize: "12px", position: "absolute", width: "calc(100% - 60px)", height: "60px", boxSizing: "border-box", margin: 0, padding: 0, paddingRight: "10px", overflowWrap: "break-word", display: "flex", flexDirection: "column", justifyContent: "center" }, style.errorMessage) }, (0, locale_1.format)(locale.format, error)));
}
renderLabels() {
const colors = this.colors, style = this.style, error = this.props.error || this.state.error, errorLine = error ? error.line : -1, lines = this.state.lines ? this.state.lines : 1;
let labels = new Array(lines);
for (let i = 0; i < lines - 1; i++)
labels[i] = i + 1;
return labels.map((number) => {
const color = number !== errorLine ? colors.default : "red";
return (react_1.default.createElement("div", { key: number, style: Object.assign(Object.assign({}, style.labels), { color: color }) }, number));
});
}
createMarkup(markupText) {
if (markupText === undefined)
return { __html: "" };
return { __html: "" + markupText };
}
newSpan(i, token, depth) {
let colors = this.colors, type = token.type, string = token.string;
let color = "";
switch (type) {
case "string":
case "number":
case "primitive":
case "error":
color = colors[token.type];
break;
case "key":
if (string === " ")
color = colors.keys_whiteSpace;
else
color = colors.keys;
break;
case "symbol":
if (string === ":")
color = colors.colon;
else
color = colors.default;
break;
default:
color = colors.default;
break;
}
if (string.length !== string.replace(/</g, "").replace(/>/g, "").length)
string = "<xmp style=display:inline;>" + string + "</xmp>";
return ("<span" +
' type="' +
type +
'"' +
' value="' +
string +
'"' +
' depth="' +
depth +
'"' +
' style="color:' +
color +
'"' +
">" +
string +
"</span>");
}
getCursorPosition(countBR) {
/**
* Need to deprecate countBR
* It is used to differenciate between good markup render, and aux render when error found
* Adjustments based on coundBR account for usage of <br> instead of <span> for linebreaks to determine acurate cursor position
* Find a way to consolidate render styles
*/
const isChildOf = (node) => {
while (node !== null) {
if (node === this.refContent)
return true;
node = node.parentNode;
}
return false;
};
let selection = window.getSelection(), charCount = -1, linebreakCount = 0, node;
if (selection.focusNode && isChildOf(selection.focusNode)) {
node = selection.focusNode;
charCount = selection.focusOffset;
while (node) {
if (node === this.refContent)
break;
if (node.previousSibling) {
node = node.previousSibling;
if (countBR)
if (node.nodeName === "BR")
linebreakCount++;
charCount += node.textContent.length;
}
else {
node = node.parentNode;
if (node === null)
break;
}
}
}
return charCount + linebreakCount;
}
setCursorPosition(nextPosition) {
if ([false, null, undefined].indexOf(nextPosition) > -1)
return;
const createRange = (node, chars, range) => {
if (!range) {
range = document.createRange();
range.selectNode(node);
range.setStart(node, 0);
}
if (chars.count === 0) {
range.setEnd(node, chars.count);
}
else if (node && chars.count > 0) {
if (node.nodeType === Node.TEXT_NODE) {
if (node.textContent.length < chars.count)
chars.count -= node.textContent.length;
else {
range.setEnd(node, chars.count);
chars.count = 0;
}
}
else
for (let lp = 0; lp < node.childNodes.length; lp++) {
range = createRange(node.childNodes[lp], chars, range);
if (chars.count === 0)
break;
}
}
return range;
};
const setPosition = (chars) => {
if (chars < 0)
return;
let selection = window.getSelection(), range = createRange(this.refContent, { count: chars });
if (!range)
return;
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
};
if (nextPosition > 0)
setPosition(nextPosition);
else
this.refContent.focus();
}
update(cursorOffset = 0, updateCursorPosition = true) {
const container = this.refContent, data = this.tokenize(container);
if ("onChange" in this.props) {
const jsObject = this.decodePlaceholder(data.jsObject);
this.props.onChange({
plainText: data.indented,
markupText: data.markup,
json: data.json,
jsObject,
lines: data.lines,
error: data.error,
});
}
let cursorPosition = this.getCursorPosition(data.error) + cursorOffset;
this.updateTime = false;
this.setState({
plainText: data.indented,
markupText: data.markup,
json: data.json,
jsObject: data.jsObject,
lines: data.lines,
error: data.error,
isLoading: false,
});
if (updateCursorPosition)
this.setCursorPosition(cursorPosition);
}
scheduledUpdate() {
if ("onKeyPressUpdate" in this.props)
if (this.props.onKeyPressUpdate === false)
return;
const { updateTime } = this;
if (updateTime === false || updateTime > new Date().getTime()) {
return;
}
this.update();
}
setUpdateTime() {
if ("onKeyPressUpdate" in this.props)
if (this.props.onKeyPressUpdate === false)
return;
this.updateTime = new Date().getTime() + this.waitAfterKeyPress;
this.setState({ isLoading: true });
}
stopEvent(event) {
if (!event)
return;
event.preventDefault();
event.stopPropagation();
}
onKeyPress(event) {
const ctrlOrMetaIsPressed = event.ctrlKey || event.metaKey;
if (this.props.viewOnly && !ctrlOrMetaIsPressed)
this.stopEvent(event);
if (!ctrlOrMetaIsPressed)
this.setUpdateTime();
}
onKeyDown(event) {
const viewOnly = !!this.props.viewOnly;
const ctrlOrMetaIsPressed = event.ctrlKey || event.metaKey;
switch (event.key) {
case "Tab":
this.stopEvent(event);
if (viewOnly)
break;
document.execCommand("insertText", false, " ");
this.setUpdateTime();
break;
case "Backspace":
case "Delete":
if (viewOnly)
this.stopEvent(event);
this.setUpdateTime();
break;
case "ArrowLeft":
case "ArrowRight":
case "ArrowUp":
case "ArrowDown":
this.setUpdateTime();
break;
case "a":
case "c":
if (viewOnly && !ctrlOrMetaIsPressed)
this.stopEvent(event);
break;
default:
if (viewOnly)
this.stopEvent(event);
break;
}
}
onPaste(event) {
var _a;
if (this.props.viewOnly) {
this.stopEvent(event);
}
else {
event.preventDefault();
let text = (_a = event.clipboardData.getData("text/plain")) === null || _a === void 0 ? void 0 : _a.replace(/(\r\n|\n|\r|\t|\u200B)/gm, '');
document.execCommand("insertText", false, text);
}
this.update();
}
onClick() {
if ("viewOnly" in this.props)
if (this.props.viewOnly)
return;
}
onBlur() {
if ("viewOnly" in this.props)
if (this.props.viewOnly)
return;
const container = this.refContent, data = this.tokenize(container);
if ("onBlur" in this.props) {
const jsObject = this.decodePlaceholder(data.jsObject);
this.props.onBlur({
plainText: data.indented,
markupText: data.markup,
json: data.json,
jsObject,
lines: data.lines,
error: data.error,
});
}
}
onScroll(event) {
this.refLabels.scrollTop = event.target.scrollTop;
}
componentDidUpdate() {
if (!this.state.isLoading) {
this.updateInternalProps();
this.showPlaceholder();
}
}
componentDidMount() {
this.showPlaceholder();
}
componentWillUnmount() {
if (this.timer)
clearInterval(this.timer);
this.mappedKeys.clear();
}
isArray(value) {
return Array.isArray(value);
}
isObject(value) {
return typeof value === 'object' && !this.isArray(value) && value !== null;
}
isString(value) {
return typeof value === 'string' || value instanceof String;
}
encodePlaceholder(placeholder) {
try {
if (!this.isObject(placeholder))
return;
for (const [key, value] of Object.entries(placeholder)) {
const isArray = this.isArray(value);
if (!this.isString(value) && !isArray)
continue;
if (isArray) {
value.forEach((val, index) => {
try {
placeholder[key][index] = JSON.parse(val);
this.mappedKeys.add({ key, type: "array" });
}
catch (e) {
placeholder[key][index] = val;
}
});
}
else {
try {
placeholder[key] = JSON.parse(value);
this.mappedKeys.add({ key });
}
catch (e) {
placeholder[key] = value;
}
}
}
}
catch (e) {
console.error(e);
}
}
decodePlaceholder(placeholder) {
if (!placeholder)
return null;
const decodedPlaceholder = structuredClone(placeholder);
Array.from(this.mappedKeys).forEach(item => {
const value = placeholder[item.key];
if (item.type === "array") {
value.forEach((val, index) => {
try {
decodedPlaceholder[item.key][index] = JSON.stringify(val);
}
catch (e) {
decodedPlaceholder[item.key][index] = val;
}
});
}
else {
try {
decodedPlaceholder[item.key] = JSON.stringify(value);
}
catch (e) {
console.error(e);
}
}
});
return decodedPlaceholder;
}
showPlaceholder() {
const placeholderDoesNotExist = !("placeholder" in this.props);
if (placeholderDoesNotExist)
return;
const { placeholder } = this.props;
const placeholderHasEmptyValues = [undefined, null].indexOf(placeholder) > -1;
if (placeholderHasEmptyValues)
return;
this.encodePlaceholder(placeholder);
const { prevPlaceholder, jsObject } = this.state;
const { resetConfiguration } = this;
const placeholderDataType = (0, mitsuketa_1.getType)(placeholder);
const unexpectedDataType = ["object", "array"].indexOf(placeholderDataType) === -1;
if (unexpectedDataType)
err_1.default.throwError("showPlaceholder", "placeholder", "either an object or an array");
const samePlaceholderValues = (0, mitsuketa_1.identical)(placeholder, prevPlaceholder);
// Component will always re-render when new placeholder value is any different from previous placeholder value.
let componentShouldUpdate = !samePlaceholderValues;
if (!componentShouldUpdate) {
if (resetConfiguration) {
/**
* If 'reset' property is set true or is truthy,
* any difference between placeholder and current value
* should trigger component re-render
*/
if (jsObject !== undefined)
componentShouldUpdate = !(0, mitsuketa_1.identical)(placeholder, jsObject);
}
}
if (!componentShouldUpdate)
return;
const data = this.tokenize(placeholder);
this.setState({
prevPlaceholder: placeholder,
plainText: data.indentation,
markupText: data.markup,
lines: data.lines,
error: data.error,
isLoading: false,
});
}
tokenize(something) {
var _a, _b;
if (typeof something !== "object")
return console.error("tokenize() expects object type properties only. Got '" +
typeof something +
"' type instead.");
const locale = this.props.locale || en_1.default;
const newSpan = this.newSpan;
/**
* DOM NODE || ONBLUR OR UPDATE
*/
if ("nodeType" in something) {
const containerNode = something.cloneNode(true), hasChildren = containerNode.hasChildNodes();
if (!hasChildren)
return "";
const children = containerNode.childNodes;
let buffer = {
tokens_unknown: [],
tokens_proto: [],
tokens_split: [],
tokens_fallback: [],
tokens_normalize: [],
tokens_merge: [],
tokens_plainText: "",
indented: "",
json: "",
jsObject: undefined,
markup: "",
};
for (let i = 0; i < children.length; i++) {
let child = children[i];
let info = {};
switch (child.nodeName) {
case "SPAN":
info = {
string: child.textContent,
type: child.attributes.type.textContent,
};
buffer.tokens_unknown.push(info);
break;
case "DIV":
buffer.tokens_unknown.push({
string: child.textContent,
type: "unknown",
});
break;
case "BR":
if (child.textContent === "")
buffer.tokens_unknown.push({ string: "\n", type: "unknown" });
break;
case "#text":
buffer.tokens_unknown.push({
string: child.textContent,
type: "unknown",
});
break;
case "FONT":
buffer.tokens_unknown.push({
string: child.textContent,
type: "unknown",
});
break;
default:
console.error("Unrecognized node:", { child });
break;
}
}
function quarkize(text, prefix = "") {
let buffer = {
active: false,
string: "",
number: "",
symbol: "",
space: "",
delimiter: "",
quarks: [],
};
function pushAndStore(char, type) {
switch (type) {
case "symbol":
case "delimiter":
if (buffer.active)
buffer.quarks.push({
string: buffer[buffer.active],
type: prefix + "-" + buffer.active,
});
buffer[buffer.active] = "";
buffer.active = type;
buffer[buffer.active] = char;
break;
default:
if (type !== buffer.active ||
[buffer.string, char].indexOf("\n") > -1) {
if (buffer.active)
buffer.quarks.push({
string: buffer[buffer.active],
type: prefix + "-" + buffer.active,
});
buffer[buffer.active] = "";
buffer.active = type;
buffer[buffer.active] = char;
}
else
buffer[type] += char;
break;
}
}
function finalPush() {
if (buffer.active) {
buffer.quarks.push({
string: buffer[buffer.active],
type: prefix + "-" + buffer.active,
});
buffer[buffer.active] = "";
buffer.active = false;
}
}
for (let i = 0; i < text.length; i++) {
const char = text.charAt(i);
switch (char) {
case '"':
case "'":
pushAndStore(char, "delimiter");
break;
case " ":
case "\u00A0":
pushAndStore(char, "space");
break;
case "{":
case "}":
case "[":
case "]":
case ":":
case ",":
pushAndStore(char, "symbol");
break;
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
if (buffer.active === "string")
pushAndStore(char, "string");
else
pushAndStore(char, "number");
break;
case "-":
if (i < text.length - 1)
if ("0123456789".indexOf(text.charAt(i + 1)) > -1) {
pushAndStore(char, "number");
break;
}
case ".":
if (i < text.length - 1 && i > 0)
if ("0123456789".indexOf(text.charAt(i + 1)) > -1 &&
"0123456789".indexOf(text.charAt(i - 1)) > -1) {
pushAndStore(char, "number");
break;
}
default:
pushAndStore(char, "string");
break;
}
}
finalPush();
return buffer.quarks;
}
for (let i = 0; i < buffer.tokens_unknown.length; i++) {
let token = buffer.tokens_unknown[i];
buffer.tokens_proto = buffer.tokens_proto.concat(quarkize(token.string, "proto"));
}
function validToken(string, type) {
const quotes = "'\"";
let firstChar = "", lastChar = "", quoteType = false;
switch (type) {
case "primitive":
if (["true", "false", "null", "undefined"].indexOf(string) === -1)
return false;
break;
case "string":
if (string.length < 2)
return false;
(firstChar = string.charAt(0)),
(lastChar = string.charAt(string.length - 1)),
(quoteType = quotes.indexOf(firstChar));
if (quoteType === -1)
return false;
if (firstChar !== lastChar)
return false;
for (let i = 0; i < string.length; i++) {
if (i > 0 && i < string.length - 1)
if (string.charAt(i) === quotes[quoteType])
if (string.charAt(i - 1) !== "\\")
return false;
}
break;
case "key":
if (string.length === 0)
return false;
(firstChar = string.charAt(0)),
(lastChar = string.charAt(string.length - 1)),
(quoteType = quotes.indexOf(firstChar));
if (quoteType > -1) {
if (string.length === 1)
return false;
if (firstChar !== lastChar)
return false;
for (let i = 0; i < string.length; i++) {
if (i > 0 && i < string.length - 1)
if (string.charAt(i) === quotes[quoteType])
if (string.charAt(i - 1) !== "\\")
return false;
}
}
else {
const nonAlphanumeric = "'\"`.,:;{}[]&<>=~*%\\|/-+!?@^ \xa0";
for (let i = 0; i < nonAlphanumeric.length; i++) {
const nonAlpha = nonAlphanumeric.charAt(i);
if (string.indexOf(nonAlpha) > -1)
return false;
}
}
break;
case "number":
for (let i = 0; i < string.length; i++) {
if ("0123456789".indexOf(string.charAt(i)) === -1)
if (i === 0) {
if ("-" !== string.charAt(0))
return false;
}
else if ("." !== string.charAt(i))
return false;
}
break;
case "symbol":
if (string.length > 1)
return false;
if ("{[:]},".indexOf(string) === -1)
return false;
break;
case "colon":
if (string.length > 1)
return false;
if (":" !== string)
return false;
break;
default:
return true;
break;
}
return true;
}
for (let i = 0; i < buffer.tokens_proto.length; i++) {
let token = buffer.tokens_proto[i];
if (token.type.indexOf("proto") === -1) {
if (!validToken(token.string, token.type)) {
buffer.tokens_split = buffer.tokens_split.concat(quarkize(token.string, "split"));
}
else
buffer.tokens_split.push(token);
}
else
buffer.tokens_split.push(token);
}
for (let i = 0; i < buffer.tokens_split.length; i++) {
let token = buffer.tokens_split[i];
let type = token.type, string = token.string, length = string.length, fallback = [];
if (type.indexOf("-") > -1) {
type = type.slice(type.indexOf("-") + 1);
if (type !== "string")
fallback.push("string");
fallback.push("key");
fallback.push("error");
}
let tokul = {
string: string,
length: length,
type: type,
fallback: fallback,
};
buffer.tokens_fallback.push(tokul);
}
function tokenFollowed() {
const last = buffer.tokens_normalize.length - 1;
if (last < 1)
return false;
for (let i = last; i >= 0; i--) {
const previousToken = buffer.tokens_normalize[i];
switch (previousToken.type) {
case "space":
case "linebreak":
break;
default:
return previousToken;
break;
}
}
return false;
}
let buffer2 = {
brackets: [],
stringOpen: false,
isValue: false,
};
for (let i = 0; i < buffer.tokens_fallback.length; i++) {
let token = buffer.tokens_fallback[i];
const type = token.type, string = token.string;
let normalToken = {
type: type,
string: string,
};
switch (type) {
case "symbol":
case "colon":
if (buffer2.stringOpen) {
if (buffer2.isValue)
normalToken.type = "string";
else
normalToken.type = "key";
break;
}
switch (string) {
case "[":
case "{":
buffer2.brackets.push(string);
buffer2.isValue =
buffer2.brackets[buffer2.brackets.length - 1] === "[";
break;
case "]":
case "}":
buffer2.brackets.pop();
buffer2.isValue =
buffer2.brackets[buffer2.brackets.length - 1] === "[";
break;
case ",":
if (tokenFollowed().type === "colon")
break;
buffer2.isValue =
buffer2.brackets[buffer2.brackets.length - 1] === "[";
break;
case ":":
normalToken.type = "colon";
buffer2.isValue = true;
break;
}
break;
case "delimiter":
if (buffer2.isValue)
normalToken.type = "string";
else
normalToken.type = "key";
if (!buffer2.stringOpen) {
buffer2.stringOpen = string;
break;
}
if (i > 0) {
const previousToken = buffer.tokens_fallback[i - 1], _string = previousToken.string, _type = previousToken.type, _char = _string.charAt(_string.length - 1);
if (_type === "string" && _char === "\\")
break;
}
if (buffer2.stringOpen === string) {
buffer2.stringOpen = false;
break;
}
break;
case "primitive":
case "string":
if (["false", "true", "null", "undefined"].indexOf(string) > -1) {
const lastIndex = buffer.tokens_normalize.length - 1;
if (lastIndex >= 0) {
if (buffer.tokens_normalize[lastIndex].type !== "string") {
normalToken.type = "primitive";
break;
}
normalToken.type = "string";
break;
}
normalToken.type = "primitive";
break;
}
if (string === "\n")
if (!buffer2.stringOpen) {
normalToken.type = "linebreak";
break;
}
if (buffer2.isValue)
normalToken.type = "string";
else
normalToken.type = "key";
break;
case "space":
if (buffer2.stringOpen)
if (buffer2.isValue)
normalToken.type = "string";
else
normalToken.type = "key";
break;
case "number":
if (buffer2.stringOpen)
if (buffer2.isValue)
normalToken.type = "string";
else
normalToken.type = "key";
break;
default:
break;
}
buffer.tokens_normalize.push(normalToken);
}
for (let i = 0; i < buffer.tokens_normalize.length; i++) {
const token = buffer.tokens_normalize[i];
let mergedToken = {
string: token.string,
type: token.type,
tokens: [i],
};
if (["symbol", "colon"].indexOf(token.type) === -1)
if (i + 1 < buffer.tokens_normalize.length) {
let count = 0;
for (let u = i + 1; u < buffer.tokens_normalize.length; u++) {
const nextToken = buffer.tokens_normalize[u];
if (token.type !== nextToken.type)
break;
mergedToken.string += nextToken.string;
mergedToken.tokens.push(u);