Improve doc comment rendering in markdown

This commit is contained in:
Misode
2024-11-26 01:15:36 +01:00
parent d370b4244a
commit 3a467e54b7
3 changed files with 54 additions and 28 deletions

View File

@@ -8,6 +8,7 @@ import { handleAttributes } from '@spyglassmc/mcdoc/lib/runtime/attribute/index.
import type { SimplifiedEnum, SimplifiedMcdocType, SimplifiedMcdocTypeNoUnion, SimplifiedStructType, SimplifiedStructTypePairField } from '@spyglassmc/mcdoc/lib/runtime/checker/index.js'
import { getValues } from '@spyglassmc/mcdoc/lib/runtime/completer/index.js'
import { Identifier, ItemStack } from 'deepslate'
import { marked } from 'marked'
import { useCallback, useMemo, useState } from 'preact/hooks'
import config from '../../Config.js'
import { useLocale } from '../../contexts/Locale.jsx'
@@ -490,7 +491,6 @@ function StructBody({ type: outerType, node, ctx }: Props<SimplifiedStructType>)
const keyType = simplifyType(field.key, ctx)
return <div key={`__dynamic_${index}__`} class="node">
<div class="node-header">
<Docs desc={field.desc} />
<DynamicKey keyType={keyType} valueType={field.type} parent={node} ctx={ctx} />
</div>
</div>
@@ -578,12 +578,11 @@ function StaticField({ pair, index, field, fieldKey, isToggled, expand, collapse
<div class="node-header">
{!field.optional && child === undefined && <ErrorIndicator error={{ message: locale('missing_key', localeQuote(fieldKey)), range: node.range, severity: 3 }} />}
<Errors type={childType} node={child} ctx={ctx} />
<Docs desc={field.desc} />
{canToggle && (isCollapsed
? <button class="toggle tooltipped tip-se" aria-label={`${locale('expand')}\n${locale('expand_all', 'Ctrl')}`} onClick={expand}>{Octicon.chevron_right}</button>
: <button class="toggle tooltipped tip-se" aria-label={`${locale('collapse')}\n${locale('collapse_all', 'Ctrl')}`} onClick={collapse}>{Octicon.chevron_down}</button>
)}
<Key label={fieldKey} />
<Key label={fieldKey} doc={field.desc} />
{!isCollapsed && <Head type={childType} node={child} optional={field.optional} ctx={fieldCtx} />}
</div>
{!isCollapsed && <Body type={childType} node={child} optional={field.optional} ctx={fieldCtx} />}
@@ -598,9 +597,10 @@ interface DynamicKeyProps {
}
function DynamicKey({ keyType, valueType, parent, ctx }: DynamicKeyProps) {
const { locale } = useLocale()
const [key, setKey] = useState<string>('')
const [key, setKey] = useState<string>()
const keyNode = useMemo(() => {
if (key === undefined) return undefined
const node = JsonStringNode.mock(core.Range.create(0))
node.value = key
return node
@@ -618,7 +618,10 @@ function DynamicKey({ keyType, valueType, parent, ctx }: DynamicKeyProps) {
}, [ctx, makeKeyEdit])
const addKey = useCallback(() => {
setKey('')
if (!keyNode) {
return
}
setKey(undefined)
ctx.makeEdit((range) => {
const valueNode = getDefault(simplifyType(valueType, ctx, { key: keyNode, parent }), range, ctx)
const newPair: core.PairNode<JsonStringNode, JsonNode> = {
@@ -636,7 +639,7 @@ function DynamicKey({ keyType, valueType, parent, ctx }: DynamicKeyProps) {
return <>
<Head type={keyType} optional={true} node={keyNode} ctx={keyCtx} />
<button class="add tooltipped tip-se" aria-label={locale('add_key')} onClick={addKey} disabled={key.length === 0}>{Octicon.plus_circle}</button>
<button class="add tooltipped tip-se" aria-label={locale('add_key')} onClick={addKey} disabled={!key || key.length === 0}>{Octicon.plus_circle}</button>
</>
}
@@ -1124,10 +1127,16 @@ function selectAnyType(node: JsonNode | undefined) {
interface KeyProps {
label: string | number | boolean
doc?: string
raw?: boolean
}
function Key({ label, raw }: KeyProps) {
return <label>{raw ? label.toString() : formatIdentifier(label.toString())}</label>
function Key({ label, doc, raw }: KeyProps) {
const [shown, setShown] = useFocus()
return <label onClick={() => setShown(true)}>
<span class={doc ? `underline ${shown ? '' : 'decoration-dotted hover:decoration-solid'}` : ''}>{raw ? label.toString() : formatIdentifier(label.toString())}</span>
{doc && <div class={`node-doc ${shown ? '' : 'hidden'}`} onClick={e => e.stopPropagation()} dangerouslySetInnerHTML={{ __html: marked(doc) }}></div>}
</label>
}
interface ErrorsProps {
@@ -1170,22 +1179,6 @@ function ErrorIndicator({ error }: ErrorIndicatorProps) {
</div>
}
interface DocsProps {
desc: string | undefined
}
function Docs({ desc }: DocsProps) {
if (!desc || desc.length === 0) {
return <></>
}
const [active, setActive] = useFocus()
return <div class={`node-icon node-help ${active ? 'show' : ''}`} onClick={() => setActive()}>
{Octicon.info}
<span class="icon-popup">{desc}</span>
</div>
}
function useToggles() {
const [toggleState, setToggleState] = useState(new Map<string, boolean>())
const [toggleAll, setToggleAll] = useState<boolean | undefined>(undefined)

View File

@@ -304,7 +304,7 @@ export class SpyglassService {
idOmitDefaultNamespace: false,
undeclaredSymbol: [
{
if: { category: ['bossbar', 'objective', 'team'] },
if: { category: ['bossbar', 'objective', 'team', 'shader'] },
then: { declare: 'block' },
},
...core.VanillaConfig.lint.undeclaredSymbol as any[],

View File

@@ -74,11 +74,15 @@
.node-header > label {
align-self: flex-start;
padding: 0 9px;
line-height: 1.94rem;
background-color: var(--node-background-label);
}
.node-header > label > span {
padding: 0 9px;
white-space: nowrap;
user-select: none;
background-color: var(--node-background-label);
text-decoration-color: var(--node-text-dimmed);
}
.node-header > label > .item-display {
@@ -86,6 +90,35 @@
height: 32px;
}
.node-doc {
position: absolute;
font-size: 16px;
line-height: 1.3;
z-index: 10;
margin-top: -1px;
margin-left: 3px;
padding: 4px 9px;
border-radius: 4px;
border: 1px solid;
color: var(--node-text-dimmed);
border-color: var(--node-border);
background-color: var(--node-background-label);
box-shadow: 0 1px 7px -2px #000;
}
.node-header > label > span:hover + .node-doc {
display: block;
}
.node-doc code {
color: var(--accent-primary);
}
.node-doc ul {
padding-left: 16px;
list-style-type: disc;
}
.node-header > input {
font-size: 18px;
padding-left: 9px;
@@ -126,7 +159,7 @@
background-color: var(--node-background-hover);
}
.node-header a {
.node-header > a {
display: flex;
align-items: center;
font-size: 18px;