mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-24 07:37:10 +00:00
109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
import type { DocAndNode, Range } from '@spyglassmc/core'
|
|
import type { JsonNode } from '@spyglassmc/json'
|
|
import { JsonFileNode } from '@spyglassmc/json'
|
|
import type { AttributeValue, McdocType } from '@spyglassmc/mcdoc'
|
|
import { useCallback, useErrorBoundary, useMemo } from 'preact/hooks'
|
|
import { disectFilePath, useLocale, useVersion } from '../../contexts/index.js'
|
|
import { useDocAndNode, useSpyglass } from '../../contexts/Spyglass.jsx'
|
|
import type { McdocContext } from './McdocRenderer.jsx'
|
|
import { McdocRoot, simplifyType } from './McdocRenderer.jsx'
|
|
|
|
type TreePanelProps = {
|
|
docAndNode: DocAndNode,
|
|
onError: (message: string) => unknown,
|
|
}
|
|
export function Tree({ docAndNode: original, onError }: TreePanelProps) {
|
|
const { lang } = useLocale()
|
|
const { version } = useVersion()
|
|
const { service } = useSpyglass()
|
|
|
|
if (lang === 'none') return <></>
|
|
|
|
const docAndNode = useDocAndNode(original)
|
|
const fileChild = docAndNode.node.children[0]
|
|
if (!JsonFileNode.is(fileChild)) {
|
|
return <></>
|
|
}
|
|
|
|
const [error] = useErrorBoundary(e => {
|
|
onError(`Error rendering the tree: ${e.message}`)
|
|
console.error(e)
|
|
})
|
|
if (error) return <></>
|
|
|
|
const makeEdit = useCallback((edit: (range: Range) => JsonNode | undefined) => {
|
|
if (!service) {
|
|
return
|
|
}
|
|
service.applyEdit(docAndNode.doc.uri, (fileNode) => {
|
|
const jsonFile = fileNode.children[0]
|
|
if (JsonFileNode.is(jsonFile)) {
|
|
const original = jsonFile.children[0]
|
|
const newNode = edit(original.range)
|
|
if (newNode !== undefined) {
|
|
newNode.parent = fileNode
|
|
fileNode.children[0] = newNode
|
|
}
|
|
}
|
|
})
|
|
}, [service, docAndNode])
|
|
|
|
const ctx = useMemo<McdocContext | undefined>(() => {
|
|
if (!service) {
|
|
return undefined
|
|
}
|
|
const errors = [
|
|
...docAndNode.node.binderErrors ?? [],
|
|
...docAndNode.node.checkerErrors ?? [],
|
|
...docAndNode.node.linterErrors ?? [],
|
|
]
|
|
return service.getCheckerContext(docAndNode.doc, errors)
|
|
}, [docAndNode, service])
|
|
|
|
const type = useMemo(() => {
|
|
if (!ctx) {
|
|
return undefined
|
|
}
|
|
const path = original.doc.uri
|
|
.replace(/^file:\/\/\/project\//, '')
|
|
.replace(/\.json$/, '')
|
|
const res = disectFilePath(path, version)
|
|
if (!res) {
|
|
return undefined
|
|
}
|
|
return simplifyType(getRootType(res.type), ctx)
|
|
}, [original.doc.uri, version, ctx])
|
|
|
|
return <div class="tree node-root" data-cy="tree">
|
|
{(ctx && type) && <McdocRoot type={type} node={fileChild.children[0]} makeEdit={makeEdit} ctx={ctx} />}
|
|
</div>
|
|
}
|
|
|
|
function getRootType(id: string): McdocType {
|
|
if (id === 'pack_mcmeta') {
|
|
return { kind: 'reference', path: '::java::pack::Pack' }
|
|
}
|
|
if (id === 'text_component' ) {
|
|
return { kind: 'reference', path: '::java::server::util::text::Text' }
|
|
}
|
|
if (id.startsWith('tag/')) {
|
|
const attribute: AttributeValue = {
|
|
kind: 'tree',
|
|
values: {
|
|
registry: { kind: 'literal', value: { kind: 'string', value: id.slice(4) } },
|
|
tags: { kind: 'literal', value: { kind: 'string', value: 'allowed' } },
|
|
},
|
|
}
|
|
return {
|
|
kind: 'concrete',
|
|
child: { kind: 'reference', path: '::java::data::tag::Tag' },
|
|
typeArgs: [{ kind: 'string', attributes: [{ name: 'id', value: attribute }] }],
|
|
}
|
|
}
|
|
return {
|
|
kind: 'dispatcher',
|
|
registry: 'minecraft:resource',
|
|
parallelIndices: [{ kind: 'static', value: id }],
|
|
}
|
|
}
|