2024-01-24 02:27:12 +00:00
|
|
|
import React, { ReactNode, useState } from "react";
|
|
|
|
import styles from "./OrgAst.module.css";
|
2024-01-27 22:01:09 +00:00
|
|
|
import { Fragment } from "react";
|
2024-01-24 02:27:12 +00:00
|
|
|
|
2024-01-27 19:30:15 +00:00
|
|
|
const OrgAst = (props: {
|
|
|
|
setHighlight: Function;
|
|
|
|
clearHighlights: Function;
|
2024-01-27 22:01:09 +00:00
|
|
|
astTree: any;
|
2024-01-27 19:30:15 +00:00
|
|
|
value: string;
|
|
|
|
}) => {
|
2024-01-27 23:39:54 +00:00
|
|
|
const [selectedNode, setSelectedNode] = useState<OrgNodeReference | null>(
|
|
|
|
null,
|
|
|
|
);
|
|
|
|
const [hoveredNode, setHoveredNode] = useState<OrgNodeReference | null>(null);
|
2024-01-27 19:24:32 +00:00
|
|
|
|
|
|
|
function selectNode(uid: string, start: number, end: number) {
|
2024-01-27 23:39:54 +00:00
|
|
|
const new_node: OrgNodeReference = { uid: uid, start: start, end: end };
|
|
|
|
props.setHighlight([new_node, hoveredNode].filter((node) => node !== null));
|
|
|
|
setSelectedNode({ uid: uid, start: start, end: end });
|
|
|
|
}
|
|
|
|
|
|
|
|
function startHoverNode(uid: string, start: number, end: number) {
|
|
|
|
const new_node: OrgNodeReference = { uid: uid, start: start, end: end };
|
|
|
|
props.setHighlight(
|
|
|
|
[selectedNode, new_node].filter((node) => node !== null),
|
|
|
|
);
|
|
|
|
setHoveredNode({ uid: uid, start: start, end: end });
|
|
|
|
}
|
|
|
|
|
|
|
|
function endHoverNode(uid: string) {
|
|
|
|
props.setHighlight([selectedNode].filter((node) => node !== null));
|
|
|
|
setHoveredNode(null);
|
2024-01-27 19:04:44 +00:00
|
|
|
}
|
|
|
|
|
2024-01-27 19:56:12 +00:00
|
|
|
if (props.astTree.status !== "success") {
|
|
|
|
return <div className={styles.OrgAst}>Error! {props.astTree.content}</div>;
|
2024-01-24 02:27:12 +00:00
|
|
|
} else {
|
|
|
|
return (
|
2024-01-24 03:06:47 +00:00
|
|
|
<div className={styles.OrgAst}>
|
2024-01-27 19:30:15 +00:00
|
|
|
<OrgAstNode
|
2024-01-27 20:01:37 +00:00
|
|
|
key="^"
|
|
|
|
uid="^"
|
2024-01-27 19:30:15 +00:00
|
|
|
selectNode={selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={startHoverNode}
|
|
|
|
endHoverNode={endHoverNode}
|
2024-01-27 19:56:12 +00:00
|
|
|
node={props.astTree.content}
|
2024-01-27 19:30:15 +00:00
|
|
|
selectedNode={selectedNode}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.value}
|
2024-01-27 19:30:15 +00:00
|
|
|
/>
|
2024-01-24 03:06:47 +00:00
|
|
|
</div>
|
2024-01-24 02:27:12 +00:00
|
|
|
);
|
|
|
|
}
|
2024-01-24 03:06:47 +00:00
|
|
|
};
|
2024-01-24 02:27:12 +00:00
|
|
|
|
2024-01-27 23:39:54 +00:00
|
|
|
interface OrgNodeReference {
|
|
|
|
uid: string;
|
|
|
|
start: number;
|
|
|
|
end: number;
|
|
|
|
}
|
|
|
|
|
2024-01-27 19:30:15 +00:00
|
|
|
const OrgAstNode = (props: {
|
|
|
|
selectNode: Function;
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode: Function;
|
|
|
|
endHoverNode: Function;
|
2024-01-27 19:30:15 +00:00
|
|
|
node: any;
|
2024-01-27 20:01:37 +00:00
|
|
|
uid: string;
|
2024-01-27 23:39:54 +00:00
|
|
|
selectedNode: OrgNodeReference | null;
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource: string;
|
2024-01-27 19:30:15 +00:00
|
|
|
}) => {
|
2024-01-27 23:39:54 +00:00
|
|
|
const [isHovered, setIsHovered] = useState(false);
|
|
|
|
|
2024-01-27 19:04:44 +00:00
|
|
|
function selectNode() {
|
2024-01-27 19:30:15 +00:00
|
|
|
props.selectNode(
|
2024-01-27 20:01:37 +00:00
|
|
|
props.uid,
|
2024-01-27 23:39:54 +00:00
|
|
|
props.node["standard-properties"]["begin"],
|
|
|
|
props.node["standard-properties"]["end"],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hoverNode() {
|
|
|
|
props.startHoverNode(
|
|
|
|
props.uid,
|
|
|
|
props.node["standard-properties"]["begin"],
|
|
|
|
props.node["standard-properties"]["end"],
|
2024-01-27 19:30:15 +00:00
|
|
|
);
|
2024-01-27 23:39:54 +00:00
|
|
|
setIsHovered(true);
|
2024-01-27 19:04:44 +00:00
|
|
|
}
|
|
|
|
|
2024-01-27 23:39:54 +00:00
|
|
|
function endHoverNode() {
|
|
|
|
props.endHoverNode(props.uid);
|
|
|
|
setIsHovered(false);
|
|
|
|
}
|
|
|
|
|
2024-01-28 02:46:44 +00:00
|
|
|
function unicodeAwareSlice(text: string, start: number, end: number) {
|
|
|
|
// Boooo javascript
|
|
|
|
let i = 0;
|
|
|
|
let output = "";
|
|
|
|
for (const chr of text) {
|
|
|
|
if (i >= end) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i >= start) {
|
|
|
|
output += chr;
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2024-01-27 23:39:54 +00:00
|
|
|
let nodeClassName = styles.OrgAstNode;
|
|
|
|
if (props.selectedNode?.uid === props.uid) {
|
|
|
|
nodeClassName = nodeClassName + " " + styles.selected;
|
|
|
|
}
|
|
|
|
if (isHovered) {
|
|
|
|
nodeClassName = nodeClassName + " " + styles.hovered;
|
|
|
|
}
|
2024-01-27 19:04:44 +00:00
|
|
|
|
2024-01-28 02:46:44 +00:00
|
|
|
const selfSource = JSON.stringify(
|
|
|
|
unicodeAwareSlice(
|
|
|
|
props.fullSource,
|
|
|
|
props.node["standard-properties"].begin - 1,
|
|
|
|
props.node["standard-properties"].end - 1,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
2024-01-28 03:04:22 +00:00
|
|
|
if (props.node["ast-node"] === "plain-text") {
|
|
|
|
return (
|
|
|
|
<div className={nodeClassName}>
|
|
|
|
<div
|
|
|
|
className={styles.OrgAstNodeType}
|
|
|
|
onClick={selectNode}
|
|
|
|
onMouseEnter={hoverNode}
|
|
|
|
onMouseLeave={endHoverNode}
|
|
|
|
title={selfSource}
|
|
|
|
>
|
|
|
|
<span>{props.node["ast-node"]}</span>
|
|
|
|
<span>{selfSource}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-01-24 02:27:12 +00:00
|
|
|
return (
|
2024-01-27 19:04:44 +00:00
|
|
|
<div className={nodeClassName}>
|
2024-01-27 23:39:54 +00:00
|
|
|
<div
|
|
|
|
className={styles.OrgAstNodeType}
|
|
|
|
onClick={selectNode}
|
|
|
|
onMouseEnter={hoverNode}
|
|
|
|
onMouseLeave={endHoverNode}
|
2024-01-28 02:46:44 +00:00
|
|
|
title={selfSource}
|
2024-01-27 23:39:54 +00:00
|
|
|
>
|
2024-01-28 02:46:44 +00:00
|
|
|
<span>{props.node["ast-node"]}</span>
|
|
|
|
<span>{selfSource}</span>
|
2024-01-27 19:30:15 +00:00
|
|
|
</div>
|
2024-01-24 04:07:26 +00:00
|
|
|
<details>
|
2024-01-24 03:27:31 +00:00
|
|
|
<summary>Standard Properties</summary>
|
2024-01-27 22:01:09 +00:00
|
|
|
<OrgPropertiesList
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 22:01:09 +00:00
|
|
|
parentUniqueId={props.uid}
|
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
properties={props.node["standard-properties"]}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 22:01:09 +00:00
|
|
|
/>
|
2024-01-24 03:27:31 +00:00
|
|
|
</details>
|
2024-01-27 20:27:23 +00:00
|
|
|
{!!Object.keys(props.node.properties).length ? (
|
|
|
|
<>
|
|
|
|
<details>
|
|
|
|
<summary>Properties</summary>
|
2024-01-27 22:01:09 +00:00
|
|
|
<OrgPropertiesList
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 20:27:23 +00:00
|
|
|
parentUniqueId={props.uid}
|
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
properties={props.node.properties}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 20:27:23 +00:00
|
|
|
/>
|
|
|
|
</details>
|
|
|
|
</>
|
2024-01-27 22:01:09 +00:00
|
|
|
) : null}
|
2024-01-24 03:06:47 +00:00
|
|
|
{Array.isArray(props.node.children) && props.node.children.length > 0 ? (
|
2024-01-24 04:07:26 +00:00
|
|
|
<details open={true}>
|
2024-01-24 03:27:31 +00:00
|
|
|
<summary>Children</summary>
|
2024-01-24 04:07:26 +00:00
|
|
|
<div className={styles.OrgAstChildren}>
|
2024-01-27 19:30:15 +00:00
|
|
|
<OrgAstNodeList
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 20:01:37 +00:00
|
|
|
parentUniqueId={props.uid}
|
2024-01-27 19:30:15 +00:00
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
node_list={props.node.children}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 19:30:15 +00:00
|
|
|
/>
|
2024-01-24 04:07:26 +00:00
|
|
|
</div>
|
2024-01-24 03:27:31 +00:00
|
|
|
</details>
|
2024-01-24 03:06:47 +00:00
|
|
|
) : null}
|
2024-01-24 02:27:12 +00:00
|
|
|
</div>
|
|
|
|
);
|
2024-01-24 03:06:47 +00:00
|
|
|
};
|
2024-01-24 02:27:12 +00:00
|
|
|
|
2024-01-27 19:30:15 +00:00
|
|
|
const OrgAstNodeList = (props: {
|
|
|
|
selectNode: Function;
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode: Function;
|
|
|
|
endHoverNode: Function;
|
2024-01-27 19:30:15 +00:00
|
|
|
parentUniqueId: string;
|
2024-01-27 23:39:54 +00:00
|
|
|
selectedNode: OrgNodeReference | null;
|
2024-01-27 19:30:15 +00:00
|
|
|
node_list: any[];
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource: string;
|
2024-01-27 19:30:15 +00:00
|
|
|
}): React.JSX.Element[] => {
|
2024-01-24 04:07:26 +00:00
|
|
|
return props.node_list.map((node) => {
|
2024-01-27 22:01:09 +00:00
|
|
|
const uid =
|
|
|
|
props.parentUniqueId +
|
|
|
|
"_" +
|
|
|
|
node["ast-node"] +
|
|
|
|
"/" +
|
|
|
|
node["standard-properties"]["begin"] +
|
|
|
|
"/" +
|
|
|
|
node["standard-properties"]["end"] +
|
|
|
|
"#";
|
2024-01-27 19:30:15 +00:00
|
|
|
return (
|
|
|
|
<OrgAstNode
|
2024-01-27 20:01:37 +00:00
|
|
|
key={uid}
|
|
|
|
uid={uid}
|
2024-01-27 19:30:15 +00:00
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 19:30:15 +00:00
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
node={node}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 19:30:15 +00:00
|
|
|
/>
|
|
|
|
);
|
2024-01-24 04:07:26 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-01-27 20:27:23 +00:00
|
|
|
const OrgPropertiesList = (props: {
|
|
|
|
selectNode: Function;
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode: Function;
|
|
|
|
endHoverNode: Function;
|
2024-01-27 20:27:23 +00:00
|
|
|
parentUniqueId: string;
|
2024-01-27 23:39:54 +00:00
|
|
|
selectedNode: OrgNodeReference | null;
|
2024-01-27 20:27:23 +00:00
|
|
|
properties: Object;
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource: string;
|
2024-01-27 20:27:23 +00:00
|
|
|
}): React.JSX.Element => {
|
2024-01-27 22:01:09 +00:00
|
|
|
const entries = Object.entries(props.properties)
|
|
|
|
.sort((a, b) => {
|
|
|
|
if (a[0] < b[0]) {
|
|
|
|
return -1;
|
|
|
|
} else if (a[0] > b[0]) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
})
|
2024-01-27 22:07:17 +00:00
|
|
|
.filter((entry) => {
|
|
|
|
return !(is_object(entry[1]) && entry[1]["noop"] == "Noop");
|
|
|
|
})
|
2024-01-27 22:01:09 +00:00
|
|
|
.map(([key, value]) => {
|
|
|
|
return (
|
|
|
|
<Fragment key={key}>
|
|
|
|
<tr>
|
|
|
|
<th scope="row">{key}:</th>
|
2024-01-27 22:19:37 +00:00
|
|
|
<td>
|
|
|
|
<OrgPropertyValue
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 22:19:37 +00:00
|
|
|
parentUniqueId={props.parentUniqueId}
|
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
value={value}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 22:19:37 +00:00
|
|
|
/>
|
|
|
|
</td>
|
2024-01-27 22:01:09 +00:00
|
|
|
</tr>
|
|
|
|
</Fragment>
|
|
|
|
);
|
|
|
|
});
|
2024-01-27 20:27:23 +00:00
|
|
|
return (
|
2024-01-27 21:38:34 +00:00
|
|
|
<table className={styles.OrgAstProperties}>
|
2024-01-27 22:01:09 +00:00
|
|
|
<tbody>{entries}</tbody>
|
2024-01-27 21:38:34 +00:00
|
|
|
</table>
|
2024-01-27 20:27:23 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2024-01-27 22:19:37 +00:00
|
|
|
const OrgPropertyValue = (props: {
|
|
|
|
selectNode: Function;
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode: Function;
|
|
|
|
endHoverNode: Function;
|
2024-01-27 22:19:37 +00:00
|
|
|
parentUniqueId: string;
|
2024-01-27 23:39:54 +00:00
|
|
|
selectedNode: OrgNodeReference | null;
|
2024-01-27 22:19:37 +00:00
|
|
|
value: any;
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource: string;
|
2024-01-27 22:19:37 +00:00
|
|
|
}): React.ReactNode => {
|
2024-01-27 23:12:51 +00:00
|
|
|
if (
|
|
|
|
props.value === null ||
|
|
|
|
is_primitive(props.value) ||
|
|
|
|
(is_array(props.value) && props.value.length === 0)
|
|
|
|
) {
|
|
|
|
return JSON.stringify(props.value);
|
|
|
|
} else if (is_list_of_ast_nodes(props.value)) {
|
|
|
|
return (
|
|
|
|
<div className={styles.OrgAstChildren}>
|
|
|
|
<OrgAstNodeList
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId={props.parentUniqueId}
|
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
node_list={props.value}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 23:12:51 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
2024-01-28 01:49:43 +00:00
|
|
|
} else if (is_optional_pair(props.value)) {
|
|
|
|
return (
|
|
|
|
<table className={styles.OrgAstOptionalPair}>
|
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<th scope="row">Optional value:</th>
|
|
|
|
<td>{JSON.stringify(props.value.optval)}</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th scope="row">Value:</th>
|
|
|
|
<td>{JSON.stringify(props.value.val)}</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
);
|
2024-01-27 23:12:51 +00:00
|
|
|
} else if (is_object_tree(props.value)) {
|
|
|
|
return (
|
|
|
|
<OrgObjectTree
|
|
|
|
selectNode={props.selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={props.startHoverNode}
|
|
|
|
endHoverNode={props.endHoverNode}
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId={props.parentUniqueId}
|
|
|
|
selectedNode={props.selectedNode}
|
|
|
|
value={props.value}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={props.fullSource}
|
2024-01-27 23:12:51 +00:00
|
|
|
/>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
alert("Unhandled property value! " + JSON.stringify(props.value));
|
|
|
|
}
|
2024-01-27 22:19:37 +00:00
|
|
|
};
|
|
|
|
|
2024-01-27 23:12:51 +00:00
|
|
|
interface OrgObjectTreeProps {
|
|
|
|
selectNode: Function;
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode: Function;
|
|
|
|
endHoverNode: Function;
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId: string;
|
2024-01-27 23:39:54 +00:00
|
|
|
selectedNode: OrgNodeReference | null;
|
2024-01-27 23:12:51 +00:00
|
|
|
value: any;
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource: string;
|
2024-01-27 23:12:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function OrgObjectTree({
|
|
|
|
selectNode,
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode,
|
|
|
|
endHoverNode,
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId,
|
|
|
|
selectedNode,
|
|
|
|
value,
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource,
|
2024-01-27 23:12:51 +00:00
|
|
|
}: OrgObjectTreeProps): React.ReactNode {
|
|
|
|
const entries = value["object-tree"].map((entry: any) => {
|
|
|
|
return (
|
|
|
|
<tbody>
|
|
|
|
<tr>
|
|
|
|
<th scope="row">Optional value:</th>
|
|
|
|
<td>
|
|
|
|
<OrgAstNodeList
|
|
|
|
selectNode={selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={startHoverNode}
|
|
|
|
endHoverNode={endHoverNode}
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId={parentUniqueId}
|
|
|
|
selectedNode={selectedNode}
|
|
|
|
node_list={entry[0]}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={fullSource}
|
2024-01-27 23:12:51 +00:00
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th scope="row">Value:</th>
|
|
|
|
<td>
|
|
|
|
<OrgAstNodeList
|
|
|
|
selectNode={selectNode}
|
2024-01-27 23:39:54 +00:00
|
|
|
startHoverNode={startHoverNode}
|
|
|
|
endHoverNode={endHoverNode}
|
2024-01-27 23:12:51 +00:00
|
|
|
parentUniqueId={parentUniqueId}
|
|
|
|
selectedNode={selectedNode}
|
|
|
|
node_list={entry[1]}
|
2024-01-28 02:46:44 +00:00
|
|
|
fullSource={fullSource}
|
2024-01-27 23:12:51 +00:00
|
|
|
/>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
return <table className={styles.OrgAstObjectTree}>{entries}</table>;
|
|
|
|
}
|
|
|
|
|
2024-01-27 22:07:17 +00:00
|
|
|
function is_object(val: any): boolean {
|
2024-01-27 22:19:37 +00:00
|
|
|
return val instanceof Object && !(val instanceof Array);
|
2024-01-27 22:07:17 +00:00
|
|
|
}
|
|
|
|
|
2024-01-27 23:12:51 +00:00
|
|
|
function is_array(val: any): boolean {
|
|
|
|
return val instanceof Array;
|
|
|
|
}
|
|
|
|
|
|
|
|
function is_primitive(val: any): boolean | null {
|
|
|
|
if (val === null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return !(val instanceof Object || val instanceof Array);
|
|
|
|
}
|
|
|
|
|
|
|
|
function is_list_of_ast_nodes(val: any): boolean {
|
|
|
|
if (!is_array(val)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return val.every((entry: any) => {
|
|
|
|
return is_object(entry) && entry.hasOwnProperty("ast-node");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-01-28 01:49:43 +00:00
|
|
|
function is_optional_pair(val: any): boolean {
|
2024-01-28 02:46:44 +00:00
|
|
|
return (
|
|
|
|
is_object(val) && val.hasOwnProperty("optval") && val.hasOwnProperty("val")
|
|
|
|
);
|
2024-01-28 01:49:43 +00:00
|
|
|
}
|
|
|
|
|
2024-01-27 23:12:51 +00:00
|
|
|
function is_object_tree(val: any): boolean {
|
|
|
|
return is_object(val) && val.hasOwnProperty("object-tree");
|
|
|
|
}
|
|
|
|
|
2024-01-27 23:39:54 +00:00
|
|
|
export { OrgAst as default, OrgNodeReference };
|