frogpot
Version:
A library to work with directed graphs that can be projected into trees.
1 lines • 50.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/components/Hierarchy.tsx","../src/path.ts","../src/util.ts","../src/search.ts","../src/graph.ts","../src/hierarchy.ts","../src/loaders/obograph/schema.ts","../src/loaders/index.ts","../src/loaders/obograph/index.ts"],"sourcesContent":["// React\nexport { default as HierarchyTree } from \"./components/Hierarchy\";\nexport { useNodeSearch } from \"./search\";\n\n// Data model\nexport { default as Graph } from \"./graph\";\nexport { default as Hierarchy } from \"./hierarchy\";\nexport { default as Path } from \"./path\";\n\n// Loaders\nexport { default as OBOGraphLoader } from \"./loaders/obograph\";\n\n// Types\nexport type { GraphNode } from \"./types\";\nexport type { OBOGraphNode } from \"./loaders/obograph\";\n","import React, { useState, useEffect, useRef, useImperativeHandle } from \"react\";\nimport Hierarchy, { HierarchyRow } from \"../hierarchy\";\nimport Path from \"../path\";\nimport { GraphNode } from \"../types\";\nimport { takeWhile } from \"../util\";\n\ntype HierarchyTreeProps<T extends GraphNode = GraphNode> = {\n hierarchy: Hierarchy<T>;\n rootURI: string;\n itemURI?: string;\n preferredPaths?: Array<string>;\n width?: number;\n onSelectNode?: (node: T) => void;\n};\n\nexport type HierarchyTreeHandle = {\n openAndFocusNode: (uri: string) => void;\n};\n\ntype HierarchyTreeState = {\n expandPaths: Set<string>;\n showPaths: Set<string>;\n selectedPath: Path;\n};\n\nconst d = {\n // width: 1000,\n tree: {\n itemHeight: 24,\n depthIndent: 16,\n },\n};\n\n// const SELECTION_MARKER = \">\";\n\nfunction drawHierarchyPath(\n tree: Array<HierarchyRow<GraphNode>>,\n el: HTMLCanvasElement,\n) {\n const ctx = el.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = window.devicePixelRatio || 1;\n\n const cssHeight = tree.length * d.tree.itemHeight;\n\n el.style.width = \"100%\";\n el.style.height = `${cssHeight}px`;\n\n const cssWidth = el.clientWidth;\n\n el.width = cssWidth * dpr;\n el.height = cssHeight * dpr;\n\n ctx.scale(dpr, dpr);\n\n ctx.clearRect(0, 0, cssWidth, cssHeight);\n ctx.strokeStyle = \"#666\";\n ctx.lineWidth = 1;\n ctx.setLineDash([1, 1]);\n ctx.beginPath();\n\n tree.forEach((originItem, i) => {\n const childItems = takeWhile(\n tree.slice(i + 1),\n item => item.depth > originItem.depth,\n );\n\n if (childItems.length === 0) return;\n\n const x0 = originItem.depth * d.tree.depthIndent + 5;\n const y0 = i * d.tree.itemHeight + d.tree.itemHeight / 2;\n\n const lastDirectChildIdx =\n childItems.findLastIndex(item => item.depth === originItem.depth + 1) + 1;\n // Draw a line down to the last direct child\n ctx.moveTo(x0, y0);\n ctx.lineTo(x0, y0 + lastDirectChildIdx * d.tree.itemHeight);\n\n childItems.forEach((childItem, i) => {\n if (childItem.depth === originItem.depth + 1) {\n // Draw a tick\n const tickWidth = d.tree.depthIndent;\n const y = y0 + (i + 1) * d.tree.itemHeight;\n ctx.moveTo(x0, y);\n ctx.lineTo(x0 + tickWidth, y);\n }\n });\n });\n ctx.stroke();\n}\n\n/*\nfunction drawPathFor(\n items: ReturnType<typeof Hierarchy.prototype.buildFlatTree>,\n curItemIdx: number,\n) {\n const originItem = items[curItemIdx]!;\n\n let pathStr = \"M5 0 \";\n let vIdx = 0;\n\n const horizontalTicksAt: Array<number> = [];\n\n for (const treeItem of items.slice(curItemIdx + 1)) {\n vIdx += 1;\n\n // This is an item one deeper in the hierarchy\n if (treeItem.depth === originItem.depth + 1) {\n horizontalTicksAt.push(vIdx);\n\n // Draw a line down to the current vertical position\n pathStr += `L 5 ${vIdx * d.tree.itemHeight - 10}`;\n\n // Draw a line horizontally and then back\n pathStr += `l ${d.tree.depthIndent - 12} 0`;\n pathStr += `m -${d.tree.depthIndent - 12} 0`;\n } else if (treeItem.depth <= originItem.depth) {\n break;\n }\n }\n\n return pathStr;\n}\n*/\n\nfunction HierarchyTree<T extends GraphNode = GraphNode>(\n props: HierarchyTreeProps<T>,\n ref: React.Ref<HierarchyTreeHandle>,\n) {\n const { hierarchy, itemURI } = props;\n const canvasRef = useRef<HTMLCanvasElement>(null);\n\n const [treeState, setTreeState] = useState<HierarchyTreeState>({\n expandPaths: new Set(),\n showPaths: new Set(),\n selectedPath: hierarchy.getPathsForNode(props.rootURI)[0]!,\n });\n\n /*\n const [showRelations, setShowRelations] = useState(false);\n */\n\n useEffect(() => {\n const expandPaths: Set<string> = new Set();\n\n let showPaths: Set<string> | null = null;\n\n if (itemURI) {\n const node = hierarchy.getNode(itemURI);\n const paths = hierarchy.getPathsForNode(node);\n showPaths = new Set(paths.map(path => path.key));\n }\n\n setTreeState(prev => ({\n ...prev,\n expandPaths,\n showPaths: showPaths ? showPaths : prev.showPaths,\n }));\n }, [itemURI]);\n\n const tree = hierarchy.projectFlatView({\n showPaths: [...treeState.showPaths].map(key => Path.fromKey(key)),\n expandPaths: [...treeState.expandPaths].map(key => Path.fromKey(key)),\n });\n\n /*\n const tree = hierarchy.buildFlatTree(item, {\n preferredPaths: usePreferredPaths ? preferredPaths : undefined,\n expandPaths: expandPaths.size > 0 ? [...expandPaths] : undefined,\n });\n */\n\n useImperativeHandle(\n ref,\n () => ({\n openAndFocusNode(uri: string) {\n const node = hierarchy.getNode(uri);\n const paths = hierarchy.getPathsForNode(node);\n const parents = paths.map(p => p.parent()).filter(p => p !== null);\n\n setTreeState(prev => {\n const expandPaths = new Set([\n ...prev.expandPaths,\n ...parents.map(p => p.key),\n ]);\n const showPaths = new Set([...paths.map(path => path.key)]);\n const selectedPath = paths[0]!;\n\n return {\n expandPaths,\n showPaths,\n selectedPath,\n };\n });\n },\n }),\n [],\n );\n\n useEffect(() => {\n const canvasEl = canvasRef.current;\n if (!canvasEl) return;\n drawHierarchyPath(tree, canvasEl);\n }, [tree]);\n\n useEffect(() => {\n const uri = treeState.selectedPath.leaf();\n if (props.onSelectNode) {\n props.onSelectNode(hierarchy.getNode(uri));\n }\n }, [treeState.selectedPath]);\n\n const expandPath = (pathKey: string) => {\n setTreeState(prev => ({\n ...prev,\n expandPaths: new Set([...prev.expandPaths, pathKey]),\n }));\n };\n\n const unexpandPath = (pathKey: string) => {\n const path = Path.fromKey(pathKey);\n\n setTreeState(prev => {\n const nextExpandPaths = [...prev.expandPaths].filter(_path => {\n return !Path.fromKey(_path).startsWith(path);\n });\n\n const nextShowPaths = [...prev.showPaths].filter(_path => {\n return !Path.fromKey(_path).startsWith(path);\n });\n\n let nextSelectedPath = treeState.selectedPath;\n\n if (\n treeState.selectedPath.startsWith(path) &&\n !treeState.selectedPath.equals(path)\n ) {\n nextSelectedPath = path;\n }\n\n return {\n selectedPath: nextSelectedPath,\n showPaths: new Set(nextShowPaths),\n expandPaths: new Set(nextExpandPaths),\n };\n });\n };\n\n const togglePathExpansion = (path: string) => {\n if (treeState.expandPaths.has(path)) {\n unexpandPath(path);\n } else {\n expandPath(path);\n }\n };\n\n return (\n <div\n tabIndex={0}\n onKeyDown={e => {\n const curIdx = tree.findIndex(({ path }) =>\n path.equals(treeState.selectedPath),\n );\n const curItem = tree[curIdx];\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (curIdx !== -1) {\n const nextIdx = curIdx + 1;\n const nextItem = tree[nextIdx];\n if (nextItem) {\n setTreeState(prev => ({\n ...prev,\n selectedPath: nextItem.path,\n }));\n }\n }\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n if (curIdx > 0) {\n const nextIdx = curIdx - 1;\n const nextItem = tree[nextIdx];\n if (nextItem) {\n setTreeState(prev => ({\n ...prev,\n selectedPath: nextItem.path,\n }));\n }\n }\n } else if (e.key === \"ArrowRight\") {\n e.preventDefault();\n if (curItem) {\n expandPath(curItem.path.key);\n }\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n if (curItem) {\n if (treeState.expandPaths.has(curItem.path.key)) {\n unexpandPath(curItem.path.key);\n } else {\n // Select previous level in hierarchy\n for (let i = curIdx; i >= 0; i--) {\n if (tree[i]?.depth === curItem.depth - 1) {\n setTreeState(prev => ({\n ...prev,\n selectedPath: tree[i]!.path,\n }));\n break;\n }\n }\n }\n }\n }\n }}\n >\n <div\n style={{\n position: \"relative\",\n border: \"1px solid #ccc\",\n width: props.width,\n }}\n >\n <canvas\n ref={canvasRef}\n style={{\n pointerEvents: \"none\",\n position: \"absolute\",\n top: 0,\n left: 0,\n }}\n />\n <div style={{ position: \"relative\" }}>\n {tree.map(({ item, depth, path }) => (\n <div\n key={path.key}\n data-path={path.key}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n\n lineHeight: `${d.tree.itemHeight}px`,\n height: `${d.tree.itemHeight}px`,\n\n paddingLeft: `${depth * d.tree.depthIndent}px`,\n\n userSelect: \"none\",\n cursor: \"pointer\",\n }}\n >\n <span\n onClick={() => togglePathExpansion(path.key)}\n style={{\n display: \"inline-block\",\n width: \"18px\",\n }}\n >\n {hierarchy.graph.childrenByURI[item.uri]!.length ===\n 0 ? null : (\n <span\n style={{\n display: \"inline-flex\",\n width: 10,\n height: 10,\n border: \"2px solid #666\",\n background: treeState.expandPaths.has(path.key)\n ? \"#ccc\"\n : \"#fff\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {treeState.expandPaths.has(path.key) ? \"\" : \"\"}\n </span>\n )}\n </span>\n <span\n style={{\n flex: 1,\n\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n textOverflow: \"ellipsis\",\n\n backgroundColor: treeState.selectedPath.equals(path)\n ? \"#f0f0f0\"\n : \"transparent\",\n }}\n title={itemURI}\n onMouseDown={e => {\n if (e.detail === 1) {\n // Single click: Select node\n setTreeState(prev => ({\n ...prev,\n selectedPath: path,\n }));\n } else if (e.detail === 2) {\n // Double click: Expand hierarchy\n togglePathExpansion(path.key);\n }\n }}\n >\n {/* showRelations ? relToParent + \" \" : \"\" */}\n {item.label}\n </span>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nexport default React.forwardRef(HierarchyTree);\n","export default class Path {\n steps: Array<string>;\n\n constructor(steps: Array<string>) {\n this.steps = steps;\n\n if (this.steps.length === 0) {\n throw new Error(\"Cannot create an empty path.\");\n }\n }\n\n get key() {\n return JSON.stringify(this.steps);\n }\n\n static fromKey(k: string) {\n return new Path(JSON.parse(k));\n }\n\n depth() {\n return this.steps.length;\n }\n\n startsWith(other: Path) {\n return other.isAncestorOf(this) || other.equals(this);\n }\n\n isAncestorOf(other: Path) {\n if (this.steps.length >= other.steps.length) return false;\n return this.steps.every((val, i) => val === other.steps[i]);\n }\n\n equals(other: Path) {\n if (other.steps.length !== this.steps.length) return false;\n return this.steps.every((v, i) => v === other.steps[i]);\n }\n\n parent(): Path | null {\n if (this.steps.length <= 1) return null;\n return new Path(this.steps.slice(0, -1));\n }\n\n child(uri: string): Path {\n return new Path([...this.steps, uri]);\n }\n\n leaf() {\n return this.steps.at(-1)!;\n }\n}\n","import { GraphNode } from \"./types\";\n\nexport function takeWhile<T>(\n arr: Array<T>,\n testFn: (item: T, i: number) => boolean,\n) {\n const ret: Array<T> = [];\n\n let i = 0;\n\n for (const item of arr) {\n i += 1;\n\n if (!testFn(item, i)) {\n break;\n }\n\n ret.push(item);\n }\n\n return ret;\n}\n\nexport function sortByLabel(a: GraphNode, b: GraphNode) {\n const aLabel = a.label;\n const bLabel = b.label;\n\n if (aLabel === bLabel) return 0;\n if (!aLabel) return -1;\n if (!bLabel) return 1;\n\n return aLabel.localeCompare(bLabel);\n}\n","import { useEffect, useRef, useState, createElement } from \"react\";\nimport MiniSearch, { SearchOptions, SearchResult } from \"minisearch\";\nimport { GraphNode } from \"./types\";\nimport Highlighter, { HighlighterProps } from \"react-highlight-words\";\n\nexport type SearchResultWithNode<T extends GraphNode> = SearchResult & {\n node: T;\n};\n\nexport class SearchEngine<T extends GraphNode> {\n items: Array<T>;\n itemsByURI: Map<string, T>;\n miniSearch: MiniSearch;\n\n constructor(items: Array<T>) {\n this.items = items;\n\n this.itemsByURI = new Map(items.map(item => [item.uri, item]));\n\n this.miniSearch = new MiniSearch({\n idField: \"uri\",\n fields: [\"label\", \"synonyms\", \"definitions\"],\n extractField: (doc, fieldName) => {\n if (fieldName === \"synonyms\" || fieldName === \"definitions\") {\n // @ts-expect-error Don't worry about cajoling this into types.\n return doc[fieldName].map(x => x.value).join(\" \");\n }\n\n return doc[fieldName];\n },\n });\n }\n\n search(\n text: string,\n options?: SearchOptions,\n ): Array<SearchResultWithNode<T>> {\n const results = this.miniSearch.search(text, options);\n\n return results.map(res => ({\n ...res,\n node: this.itemsByURI.get(res.id)!,\n }));\n }\n\n buildIndex() {\n this.miniSearch.addAll(this.items);\n }\n}\n\nexport function useSearchEngine<T extends GraphNode>(items: Array<T>) {\n const engineRef = useRef<SearchEngine<T>>(null);\n\n const rebuild = (items: Array<T>) => {\n const engine = new SearchEngine(items);\n engine.buildIndex();\n engineRef.current = engine;\n };\n\n if (engineRef.current === null) {\n rebuild(items);\n }\n\n useEffect(() => {\n rebuild(items);\n }, [items]);\n\n return { engine: engineRef.current! };\n}\n\nexport function useNodeSearch<T extends GraphNode>(nodes: Array<T>) {\n const { engine } = useSearchEngine(nodes);\n const [query, setQuery] = useState(\"\");\n const [results, setResults] = useState<Array<SearchResultWithNode<T>> | null>(\n null,\n );\n\n useEffect(() => {\n if (query.trim() === \"\") {\n setResults(null);\n return;\n }\n\n const results = engine.search(query, {\n prefix: true,\n boost: { label: 2 },\n combineWith: \"and\",\n });\n\n setResults(results);\n }, [query]);\n\n const searchWords = query.split(\" \").map(word => new RegExp(\"\\\\b\" + word));\n\n const highlightText = (\n text: string,\n props?: Omit<HighlighterProps, \"searchWords\" | \"textToHighlight\">,\n ) =>\n createElement(Highlighter, {\n textToHighlight: text,\n searchWords,\n ...props,\n });\n\n return { engine, results, query, setQuery, highlightText };\n}\n","import treeverse from \"treeverse\";\nimport { GraphNode } from \"./types\";\nimport Hierarchy from \"./hierarchy\";\nimport { sortByLabel } from \"./util\";\n\ntype Relation = {\n to: string;\n predicate: string;\n inverse: boolean;\n};\n\nexport default class Graph<T extends GraphNode> {\n roots: Array<T>;\n nodes: Array<T>;\n nodesByURI: Record<string, T>;\n\n childrenByURI: Record<string, Relation[]>;\n parentsByURI: Record<string, Relation[]>;\n\n constructor(nodes: Array<T>) {\n const nodesByURI: Record<string, T> = {};\n const parentsByURI: Record<string, Relation[]> = {};\n const childrenByURI: Record<string, Relation[]> = {};\n\n for (const node of nodes) {\n nodesByURI[node.uri] = node;\n\n for (const [relURI, termURIs] of Object.entries(node.children)) {\n termURIs.forEach(childURI => {\n if (!Object.hasOwn(childrenByURI, node.uri)) {\n childrenByURI[node.uri] = [];\n }\n\n if (!Object.hasOwn(parentsByURI, childURI)) {\n parentsByURI[childURI] = [];\n }\n\n childrenByURI[node.uri]!.push({\n to: childURI,\n predicate: relURI,\n inverse: false,\n });\n\n parentsByURI[childURI]!.push({\n to: node.uri,\n predicate: relURI,\n inverse: true,\n });\n });\n }\n\n for (const [relURI, termURIs] of Object.entries(node.parents)) {\n termURIs.forEach(parentURI => {\n if (!Object.hasOwn(parentsByURI, node.uri)) {\n parentsByURI[node.uri] = [];\n }\n\n if (!Object.hasOwn(childrenByURI, parentURI)) {\n childrenByURI[parentURI] = [];\n }\n\n parentsByURI[node.uri]!.push({\n to: parentURI,\n predicate: relURI,\n inverse: false,\n });\n\n childrenByURI[parentURI]!.push({\n to: node.uri,\n predicate: relURI,\n inverse: true,\n });\n });\n }\n\n if (!Object.hasOwn(childrenByURI, node.uri)) {\n childrenByURI[node.uri] = [];\n }\n if (!Object.hasOwn(parentsByURI, node.uri)) {\n parentsByURI[node.uri] = [];\n }\n }\n\n const roots = nodes.filter(\n item =>\n parentsByURI[item.uri]!.length === 0 &&\n childrenByURI[item.uri]!.length > 0,\n );\n\n this.roots = roots;\n this.nodes = nodes;\n this.nodesByURI = nodesByURI;\n this.parentsByURI = parentsByURI;\n this.childrenByURI = childrenByURI;\n }\n\n items() {\n return this.nodes;\n }\n\n getHierarchy(rootURI: string) {\n const item = this.getItem(rootURI);\n return new Hierarchy(item, this);\n }\n\n getRootHierarchies() {\n const ret: Map<string, Hierarchy<T>> = new Map();\n\n this.roots.forEach(root => {\n ret.set(root.uri, this.getHierarchy(root.uri));\n });\n\n return ret;\n }\n\n getItem(uri: string) {\n const item = this.nodesByURI[uri];\n\n if (item === undefined) {\n throw new Error(`No item in graph with URI ${uri}`);\n }\n return item;\n }\n\n findAllParents(item: T) {\n const parents: Array<T> = [];\n\n treeverse.breadth({\n tree: item,\n visit(item) {\n parents.push(item);\n },\n getChildren: node =>\n this.parentsByURI[node.uri]!.map(rel => this.getItem(rel.to)).sort(\n sortByLabel,\n ),\n });\n\n parents.shift();\n\n return parents;\n }\n\n findAllChildren(item: T) {\n const children: Array<T> = [];\n\n treeverse.breadth({\n tree: item,\n visit(item) {\n children.push(item);\n },\n getChildren: node =>\n this.childrenByURI[node.uri]!.map(rel => this.getItem(rel.to)).sort(\n sortByLabel,\n ),\n });\n\n children.shift();\n\n return children;\n }\n}\n","import treeverse from \"treeverse\";\n\nimport { GraphNode } from \"./types\";\nimport Path from \"./path\";\nimport Graph from \"./graph\";\nimport { sortByLabel } from \"./util\";\n\ntype FlatViewOptions = {\n showPaths?: Array<Path>;\n expandPaths?: Array<Path>;\n};\n\nexport type HierarchyRow<T extends GraphNode> = {\n item: T;\n relToParent: string | null;\n depth: number;\n path: Path;\n};\n\nexport default class Hierarchy<T extends GraphNode> {\n root: T;\n graph: Graph<T>;\n\n nodesByURI: Map<string, T>;\n nodesByPathKey: Map<string, T>;\n pathsByURI: Map<string, Path[]>;\n\n constructor(root: T, graph: Graph<T>) {\n this.root = root;\n this.graph = graph;\n this.nodesByURI = new Map();\n this.nodesByPathKey = new Map();\n this.pathsByURI = new Map();\n\n // Precompute all indexes ahead of time. This consists of:\n // 1. A map indexing nodes by URI\n // 2. A map indexing nodes by path key\n // 3. A map indexing paths by URI\n treeverse.depth({\n tree: {\n item: this.root,\n path: new Path([this.root.uri]),\n },\n\n visit: node => {\n const { item, path } = node;\n\n if (!this.pathsByURI.has(item.uri)) {\n this.pathsByURI.set(item.uri, []);\n }\n\n this.nodesByURI.set(item.uri, item);\n this.pathsByURI.get(item.uri)!.push(path);\n this.nodesByPathKey.set(path.key, item);\n },\n\n getChildren: node => {\n const { item, path } = node;\n const childRels = this.graph.childrenByURI[item.uri] ?? [];\n\n return childRels.map(rel => {\n const child = this.graph.getItem(rel.to);\n\n return {\n item: child,\n path: path.child(child.uri),\n };\n });\n },\n });\n }\n\n getNode(node: string | T | Path) {\n if (typeof node === \"string\") {\n const ret = this.nodesByURI.get(node);\n\n if (!ret) {\n throw new Error(`No item in hierarchy with URI ${node}`);\n }\n\n return ret;\n } else if (node instanceof Path) {\n const ret = this.nodesByPathKey.get(node.key);\n\n if (!ret) {\n throw new Error(`No item in hierarchy at path ${node.key}`);\n }\n\n return ret;\n } else {\n return node;\n }\n }\n\n items() {\n return [...this.nodesByURI.values()].sort(sortByLabel);\n }\n\n getPathsForNode(node: string | T) {\n const _node = this.getNode(node);\n return this.pathsByURI.get(_node.uri) ?? [];\n }\n\n // Produce a projection of this hierarchy, with only certain nodes shown or\n // expanded. Meant for producing a portion of the hierarchy suitable for\n // rendering in a UI.\n //\n // Returns a one-dimensional array of HierarchyRow objects annotated by their\n // depth.\n projectFlatView(opts: FlatViewOptions = {}) {\n const showPaths = opts.showPaths ?? [];\n const expandPaths = opts.expandPaths ?? [];\n\n const showKeys = new Set(showPaths.map(p => p.key));\n const expandKeys = new Set(expandPaths.map(p => p.key));\n\n const rows: Array<HierarchyRow<T>> = [];\n\n const shouldIterateChildren = (path: Path) => {\n // This is an expanded node-- iterate its children.\n if (expandKeys.has(path.key)) return true;\n\n // This is an ancestor of a shown path-- iterate its children.\n if (showPaths.some(showPath => path.isAncestorOf(showPath))) return true;\n\n // This node is an ancestor of an expanded path-- iterate its children.\n if (expandPaths.some(expandPath => path.isAncestorOf(expandPath)))\n return true;\n\n return false;\n };\n\n const shouldShowPath = (path: Path) => {\n const pathKey = path.key;\n\n // Always show the root\n if (path.depth() === 1) return true;\n\n // This is an expanded node\n if (expandKeys.has(pathKey)) return true;\n\n // This is a shown node\n if (showKeys.has(pathKey)) return true;\n\n for (const showPath of showPaths) {\n // This is an ancestor of an shown node\n if (path.isAncestorOf(showPath)) return true;\n }\n\n for (const expandPath of expandPaths) {\n // This is an ancestor of an expanded node\n if (path.isAncestorOf(expandPath)) return true;\n\n // This is the direct child of an expanded node\n if (path.parent()?.equals(expandPath)) return true;\n }\n\n return false;\n };\n\n treeverse.depth({\n tree: {\n item: this.root,\n path: new Path([this.root.uri]),\n depth: 0,\n relToParent: null,\n } as HierarchyRow<T>,\n\n visit(node) {\n const { item, path, depth, relToParent } = node;\n\n if (shouldShowPath(path)) {\n rows.push({ item, path, depth, relToParent });\n }\n },\n\n getChildren: node => {\n const { item, path, depth } = node;\n\n if (!shouldIterateChildren(path)) {\n return [];\n }\n\n const childRels = this.graph.childrenByURI[item.uri] ?? [];\n\n const children = childRels.map(rel => {\n const item = this.graph.getItem(rel.to);\n const relPredicate = !rel.inverse\n ? `^${rel.predicate}`\n : rel.predicate;\n\n return {\n item,\n path: path.child(item.uri),\n depth: depth + 1,\n relToParent: relPredicate,\n } as HierarchyRow<T>;\n });\n\n // Sort in reverse alphabetical order-- the last node is visited first.\n children.sort((a, b) => sortByLabel(b.item, a.item));\n\n return children;\n },\n });\n\n return rows;\n }\n}\n","import * as z from \"zod\";\n\nexport const OBOMeta = z.object({\n definition: z.optional(\n z.object({\n val: z.string(),\n pred: z.optional(z.string()),\n xrefs: z.optional(z.array(z.string())),\n get meta(): z.ZodOptional<typeof OBOMeta> {\n return z.optional(OBOMeta);\n },\n }),\n ),\n comments: z.optional(z.array(z.string())),\n subsets: z.optional(z.array(z.string())),\n synonyms: z.optional(\n z.array(\n z.object({\n synonymType: z.optional(z.string()),\n pred: z.optional(z.string()),\n val: z.string(),\n xrefs: z.optional(z.array(z.string())),\n get meta(): z.ZodOptional<typeof OBOMeta> {\n return z.optional(OBOMeta);\n },\n }),\n ),\n ),\n xrefs: z.optional(\n z.array(\n z.object({\n lbl: z.optional(z.string()),\n pred: z.optional(z.string()),\n val: z.string(),\n xrefs: z.optional(z.array(z.string())),\n get meta(): z.ZodOptional<typeof OBOMeta> {\n return z.optional(OBOMeta);\n },\n }),\n ),\n ),\n basicPropertyValues: z.optional(\n z.array(\n z.object({\n pred: z.string(),\n val: z.string(),\n xrefs: z.optional(z.array(z.string())),\n get meta(): z.ZodOptional<typeof OBOMeta> {\n return z.optional(OBOMeta);\n },\n }),\n ),\n ),\n version: z.optional(z.string()),\n deprecatd: z.optional(z.boolean()),\n});\n\nexport const OBOGraph = z.object({\n id: z.string(),\n lbl: z.optional(z.string()),\n meta: z.optional(OBOMeta),\n nodes: z.array(\n z.object({\n id: z.string(),\n lbl: z.optional(z.string()),\n type: z.literal([\"CLASS\", \"INDIVIDUAL\", \"PROPERTY\"]),\n propertyType: z.optional(z.literal([\"ANNOTATION\", \"OBJECT\", \"DATA\"])),\n meta: z.optional(OBOMeta),\n }),\n ),\n edges: z.array(\n z.object({\n sub: z.string(),\n pred: z.string(),\n obj: z.string(),\n meta: z.optional(OBOMeta),\n }),\n ),\n // logicalDefinitionAxioms,\n // domainRangeAxioms,\n // propertyChainAxioms,\n});\n\nexport const OBOGraphsSchema = z.object({\n meta: z.optional(OBOMeta),\n graphs: z.array(OBOGraph),\n});\n\nexport type OBOGraphs = z.infer<typeof OBOGraphsSchema>;\n\nexport type OBOGraph = z.infer<typeof OBOGraph>;\n","import Graph from \"../graph\";\nimport { GraphNode } from \"../types\";\n\nexport default abstract class GraphLoader<T, U extends GraphNode> {\n abstract parseGraph(graph: T): Graph<U>;\n abstract loadGraphFromString(str: string): T;\n\n fromString(str: string) {\n const graph = this.loadGraphFromString(str);\n return this.parseGraph(graph);\n }\n\n async fromURI(uri: string, options?: RequestInit) {\n const resp = await fetch(uri, options);\n\n if (!resp.ok) {\n throw Error(`Error requesting ${uri}: ${resp.status} ${resp.statusText}`);\n }\n\n const str = await resp.text();\n const graph = await this.loadGraphFromString(str);\n\n return this.parseGraph(graph);\n }\n}\n","import { OBOGraph, OBOGraphsSchema } from \"./schema\";\nimport Graph from \"../../graph\";\nimport { GraphNode } from \"../../types\";\nimport GraphLoader from \"../\";\n\nconst parentProperties: Record<string, string> = {\n is_a: \"rdfs:subClassOf\",\n \"http://purl.obolibrary.org/obo/BFO_0000050\": \"BFO:0000050\",\n};\n\nexport type OBOGraphNode = GraphNode & {\n meta?: OBOGraph[\"meta\"];\n edges: OBOGraph[\"edges\"];\n};\n\nexport default class OBOGraphLoader extends GraphLoader<\n OBOGraph,\n OBOGraphNode\n> {\n parseGraph(graph: OBOGraph) {\n const terms: Map<string, OBOGraphNode> = new Map();\n\n for (const node of graph.nodes) {\n if (node.type !== \"CLASS\") continue;\n\n const bpvs = node.meta?.basicPropertyValues || [];\n const replaced = !!bpvs.some(\n ({ pred }) => pred === \"http://purl.obolibrary.org/obo/IAO_0100001\",\n );\n\n if (replaced) continue;\n\n const synonyms = node.meta?.synonyms || [];\n const definition = node.meta?.definition;\n\n terms.set(node.id, {\n uri: node.id,\n label: node.lbl || node.id,\n definitions: definition ? [{ value: definition.val }] : [],\n synonyms: synonyms.map(syn => ({\n value: syn.val,\n })),\n parents: {},\n children: {},\n meta: node.meta,\n edges: [],\n });\n }\n\n for (const edge of graph.edges) {\n if (edge.pred in parentProperties) {\n const predID = parentProperties[edge.pred]!;\n const parents = terms.get(edge.sub)?.parents;\n if (!parents) continue;\n\n if (!Object.hasOwn(parents, predID)) {\n parents[predID] = [];\n }\n\n parents[predID]!.push(edge.obj);\n } else if (terms.has(edge.sub)) {\n terms.get(edge.sub)!.edges.push(edge);\n }\n }\n\n return new Graph([...terms.values()]);\n }\n\n loadGraphFromString(str: string): OBOGraph {\n const result = OBOGraphsSchema.safeParse(JSON.parse(str));\n\n if (!result.success) {\n console.log(result.error.issues);\n throw Error();\n }\n\n const graph = result.data.graphs[0]!;\n\n return graph;\n }\n}\n"],"mappings":"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