improved menus
This commit is contained in:
@@ -26,10 +26,13 @@ import {
|
|||||||
import { Code2, ScrollText, Variable } from 'lucide-react'
|
import { Code2, ScrollText, Variable } from 'lucide-react'
|
||||||
import {
|
import {
|
||||||
MenubarItem,
|
MenubarItem,
|
||||||
|
MenubarSeparator,
|
||||||
|
MenubarShortcut,
|
||||||
MenubarSub,
|
MenubarSub,
|
||||||
MenubarSubContent,
|
MenubarSubContent,
|
||||||
MenubarSubTrigger,
|
MenubarSubTrigger,
|
||||||
} from '../ui/menubar'
|
} from '../ui/menubar'
|
||||||
|
import { Kbd } from '../ui/kbd'
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'
|
||||||
import { InputHandle, OutputHandle } from './NodeHandles'
|
import { InputHandle, OutputHandle } from './NodeHandles'
|
||||||
import { NodeFooterEdgeIndicators } from './NodeFooterEdgeIndicators'
|
import { NodeFooterEdgeIndicators } from './NodeFooterEdgeIndicators'
|
||||||
@@ -191,31 +194,55 @@ export const ConfigNode = memo(function ConfigNode({ id, data, width, height }:
|
|||||||
const [editorHeight, editorContainerRef] = useResizeHeight(180)
|
const [editorHeight, editorContainerRef] = useResizeHeight(180)
|
||||||
|
|
||||||
const insertBlocksContent = useMemo(() => {
|
const insertBlocksContent = useMemo(() => {
|
||||||
return configType.insertBlocks.map((block, idx) =>
|
const templatingGroup = configType.insertBlocks.find(
|
||||||
isGroup(block) ? (
|
(b): b is import('../../lib/configTypes').InsertBlockGroup => isGroup(b) && b.label === 'Templating'
|
||||||
<MenubarSub key={`${block.label}-${idx}`}>
|
)
|
||||||
<MenubarSubTrigger className="text-xs">{block.label}</MenubarSubTrigger>
|
const typeBlocks = configType.insertBlocks.filter((b) => !(isGroup(b) && b.label === 'Templating'))
|
||||||
<MenubarSubContent className="min-w-[12rem]">
|
const insertShortcut = <MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
{block.items.map(({ label, snippet }) => (
|
const typeItems = typeBlocks.flatMap((block) =>
|
||||||
|
isGroup(block)
|
||||||
|
? block.items.map(({ label, snippet }) => (
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
key={label}
|
key={label}
|
||||||
className="text-xs"
|
className="text-xs flex items-center group"
|
||||||
onClick={() => insertAt(snippet, 'cursor')}
|
onClick={() => insertAt(snippet, 'cursor')}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
{insertShortcut}
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
))}
|
))
|
||||||
</MenubarSubContent>
|
: [
|
||||||
</MenubarSub>
|
|
||||||
) : (
|
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
key={block.label}
|
key={block.label}
|
||||||
className="text-xs"
|
className="text-xs flex items-center group"
|
||||||
onClick={() => insertAt(block.snippet, 'cursor')}
|
onClick={() => insertAt(block.snippet, 'cursor')}
|
||||||
>
|
>
|
||||||
{block.label}
|
{block.label}
|
||||||
</MenubarItem>
|
{insertShortcut}
|
||||||
|
</MenubarItem>,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
const templatingItems =
|
||||||
|
templatingGroup?.items.map(({ label, snippet }) => (
|
||||||
|
<MenubarItem
|
||||||
|
key={label}
|
||||||
|
className="text-xs flex items-center group"
|
||||||
|
onClick={() => insertAt(snippet, 'cursor')}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
|
</MenubarItem>
|
||||||
|
)) ?? []
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{typeItems}
|
||||||
|
{templatingItems.length > 0 && (
|
||||||
|
<>
|
||||||
|
<MenubarSeparator />
|
||||||
|
{templatingItems}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}, [configType.insertBlocks, insertAt])
|
}, [configType.insertBlocks, insertAt])
|
||||||
|
|
||||||
@@ -250,7 +277,7 @@ export const ConfigNode = memo(function ConfigNode({ id, data, width, height }:
|
|||||||
<NodeMenubar
|
<NodeMenubar
|
||||||
nodeId={id}
|
nodeId={id}
|
||||||
nodeType="config"
|
nodeType="config"
|
||||||
editInputsContent={
|
inputsMenuContent={
|
||||||
hasDependencies ? (
|
hasDependencies ? (
|
||||||
<>
|
<>
|
||||||
{connectedConfigNodes.map((n: any) => (
|
{connectedConfigNodes.map((n: any) => (
|
||||||
@@ -261,63 +288,59 @@ export const ConfigNode = memo(function ConfigNode({ id, data, width, height }:
|
|||||||
</MenubarSubTrigger>
|
</MenubarSubTrigger>
|
||||||
<MenubarSubContent>
|
<MenubarSubContent>
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
className="text-xs flex items-center group"
|
||||||
onClick={() => insertExtendsFromNode(n, 'cursor')}
|
onClick={() => insertExtendsFromNode(n, 'cursor')}
|
||||||
>
|
>
|
||||||
Extend
|
Extend
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
className="text-xs flex items-center group"
|
||||||
onClick={() => insertIncludeFromNode(n, 'cursor')}
|
onClick={() => insertIncludeFromNode(n, 'cursor')}
|
||||||
>
|
>
|
||||||
Include
|
Include
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
className="text-xs flex items-center group"
|
||||||
onClick={() => insertImportFromNode(n, 'cursor')}
|
onClick={() => insertImportFromNode(n, 'cursor')}
|
||||||
>
|
>
|
||||||
Import
|
Import
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarSubContent>
|
</MenubarSubContent>
|
||||||
</MenubarSub>
|
</MenubarSub>
|
||||||
))}
|
))}
|
||||||
{connectedVariableNodes.map((n: any) => (
|
{connectedVariableNodes.map((n: any) => (
|
||||||
<MenubarSub key={`${n.id}`}>
|
|
||||||
<MenubarSubTrigger className="text-xs flex items-center gap-2">
|
|
||||||
<Variable className="size-3.5 shrink-0" />
|
|
||||||
{n.id}
|
|
||||||
</MenubarSubTrigger>
|
|
||||||
<MenubarSubContent>
|
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
key={n.id}
|
||||||
|
className="text-xs flex items-center gap-2 group"
|
||||||
onClick={() => insertVariableReference(n, 'cursor')}
|
onClick={() => insertVariableReference(n, 'cursor')}
|
||||||
>
|
>
|
||||||
Insert
|
<Variable className="size-3.5 shrink-0" />
|
||||||
|
{n.id}
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarSubContent>
|
|
||||||
</MenubarSub>
|
|
||||||
))}
|
))}
|
||||||
{connectedFunctionNodes.map((n: any) => (
|
{connectedFunctionNodes.map((n: any) => (
|
||||||
<MenubarSub key={`${n.id}`}>
|
|
||||||
<MenubarSubTrigger className="text-xs flex items-center gap-2">
|
|
||||||
<Code2 className="size-3.5 shrink-0" />
|
|
||||||
{n.id}
|
|
||||||
</MenubarSubTrigger>
|
|
||||||
<MenubarSubContent>
|
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
key={n.id}
|
||||||
|
className="text-xs flex items-center gap-2 group"
|
||||||
onClick={() => insertFunctionCall(n, 'cursor')}
|
onClick={() => insertFunctionCall(n, 'cursor')}
|
||||||
>
|
>
|
||||||
Insert
|
<Code2 className="size-3.5 shrink-0" />
|
||||||
|
{n.id}
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarSubContent>
|
|
||||||
</MenubarSub>
|
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
) : undefined
|
) : (
|
||||||
|
<span className="text-xs text-muted-foreground px-2 py-1">Connect nodes to insert references</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
insertMenuLabel="Blocks"
|
||||||
|
insertContentDirect
|
||||||
insertTagsContent={insertBlocksContent}
|
insertTagsContent={insertBlocksContent}
|
||||||
insertTagsLabel={configType.label}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -338,7 +361,7 @@ export const ConfigNode = memo(function ConfigNode({ id, data, width, height }:
|
|||||||
|
|
||||||
<BaseNodeFooter>
|
<BaseNodeFooter>
|
||||||
<NodeFooterEdgeIndicators nodeId={id} nodeType="config">
|
<NodeFooterEdgeIndicators nodeId={id} nodeType="config">
|
||||||
{content ? `${content.length} chars` : 'none'}
|
{configType.label} · {content ? `${content.length} chars` : 'none'}
|
||||||
</NodeFooterEdgeIndicators>
|
</NodeFooterEdgeIndicators>
|
||||||
</BaseNodeFooter>
|
</BaseNodeFooter>
|
||||||
</BaseNode>
|
</BaseNode>
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { InputHandle, OutputHandle } from './NodeHandles'
|
|||||||
import { NodeFooterEdgeIndicators } from './NodeFooterEdgeIndicators'
|
import { NodeFooterEdgeIndicators } from './NodeFooterEdgeIndicators'
|
||||||
import { NodeHeaderTitle } from './NodeHeaderTitle'
|
import { NodeHeaderTitle } from './NodeHeaderTitle'
|
||||||
import { NodeMenubar } from './NodeMenubar'
|
import { NodeMenubar } from './NodeMenubar'
|
||||||
import { MenubarItem, MenubarSub, MenubarSubContent, MenubarSubTrigger } from '../ui/menubar'
|
import { MenubarItem, MenubarShortcut } from '../ui/menubar'
|
||||||
|
import { Kbd } from '../ui/kbd'
|
||||||
import { Code2, Variable } from 'lucide-react'
|
import { Code2, Variable } from 'lucide-react'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -110,43 +111,35 @@ export const FunctionNode = memo(function FunctionNode({ id, data, width, height
|
|||||||
<NodeMenubar
|
<NodeMenubar
|
||||||
nodeId={id}
|
nodeId={id}
|
||||||
nodeType="function"
|
nodeType="function"
|
||||||
editInputsContent={
|
inputsMenuContent={
|
||||||
hasConnectedInputs ? (
|
hasConnectedInputs ? (
|
||||||
<>
|
<>
|
||||||
{connectedVariableNodes.map((n: any) => (
|
{connectedVariableNodes.map((n: any) => (
|
||||||
<MenubarSub key={n.id}>
|
|
||||||
<MenubarSubTrigger className="text-xs flex items-center gap-2">
|
|
||||||
<Variable className="size-3.5 shrink-0" />
|
|
||||||
{n.id}
|
|
||||||
</MenubarSubTrigger>
|
|
||||||
<MenubarSubContent>
|
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
key={n.id}
|
||||||
|
className="text-xs flex items-center gap-2 group"
|
||||||
onClick={() => insertVariableAtCursor(n)}
|
onClick={() => insertVariableAtCursor(n)}
|
||||||
>
|
>
|
||||||
Insert at cursor
|
<Variable className="size-3.5 shrink-0" />
|
||||||
|
{n.id}
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarSubContent>
|
|
||||||
</MenubarSub>
|
|
||||||
))}
|
))}
|
||||||
{connectedFunctionNodes.map((n: any) => (
|
{connectedFunctionNodes.map((n: any) => (
|
||||||
<MenubarSub key={n.id}>
|
|
||||||
<MenubarSubTrigger className="text-xs flex items-center gap-2">
|
|
||||||
<Code2 className="size-3.5 shrink-0" />
|
|
||||||
{n.id}
|
|
||||||
</MenubarSubTrigger>
|
|
||||||
<MenubarSubContent>
|
|
||||||
<MenubarItem
|
<MenubarItem
|
||||||
className="text-xs"
|
key={n.id}
|
||||||
|
className="text-xs flex items-center gap-2 group"
|
||||||
onClick={() => insertFunctionAtCursor(n)}
|
onClick={() => insertFunctionAtCursor(n)}
|
||||||
>
|
>
|
||||||
Insert at cursor
|
<Code2 className="size-3.5 shrink-0" />
|
||||||
|
{n.id}
|
||||||
|
<MenubarShortcut className="opacity-0 group-hover:opacity-100 transition-opacity"><Kbd>Insert</Kbd></MenubarShortcut>
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarSubContent>
|
|
||||||
</MenubarSub>
|
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
) : undefined
|
) : (
|
||||||
|
<span className="text-xs text-muted-foreground px-2 py-1">Connect nodes to insert at cursor</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -167,7 +160,7 @@ export const FunctionNode = memo(function FunctionNode({ id, data, width, height
|
|||||||
|
|
||||||
<BaseNodeFooter>
|
<BaseNodeFooter>
|
||||||
<NodeFooterEdgeIndicators nodeId={id} nodeType="function">
|
<NodeFooterEdgeIndicators nodeId={id} nodeType="function">
|
||||||
{bodyValue ? `Javascript | ${bodyValue.length} chars` : 'none'}
|
{bodyValue ? `JavaScript · ${bodyValue.length} chars` : 'JavaScript · none'}
|
||||||
</NodeFooterEdgeIndicators>
|
</NodeFooterEdgeIndicators>
|
||||||
</BaseNodeFooter>
|
</BaseNodeFooter>
|
||||||
</BaseNode>
|
</BaseNode>
|
||||||
|
|||||||
@@ -20,17 +20,23 @@ type NodeType = 'config' | 'render' | 'variable' | 'function'
|
|||||||
type Props = {
|
type Props = {
|
||||||
nodeId: string
|
nodeId: string
|
||||||
nodeType: NodeType
|
nodeType: NodeType
|
||||||
/** Content for Insert → Inputs (config and function nodes only) */
|
/** Content for Insert → Inputs (function nodes); when inputsMenuContent is set, Inputs is a separate menu and this is not used in Insert */
|
||||||
editInputsContent?: React.ReactNode
|
editInputsContent?: React.ReactNode
|
||||||
|
/** When set, Inputs is rendered as its own top-level menu (config nodes); Insert then only shows markup-specific options */
|
||||||
|
inputsMenuContent?: React.ReactNode
|
||||||
/** Content for Insert → [Blocks/Tags] (e.g. type-specific snippets, config nodes) */
|
/** Content for Insert → [Blocks/Tags] (e.g. type-specific snippets, config nodes) */
|
||||||
insertTagsContent?: React.ReactNode
|
insertTagsContent?: React.ReactNode
|
||||||
/** Label for Insert submenu that shows insertTagsContent (default "Tags") */
|
/** Label for the Insert/Blocks menu trigger (default "Insert") */
|
||||||
|
insertMenuLabel?: string
|
||||||
|
/** When true, render insertTagsContent directly in the menu (no submenu level). Use for flat Blocks list. */
|
||||||
|
insertContentDirect?: boolean
|
||||||
|
/** Label for Insert submenu that shows insertTagsContent when not insertContentDirect (default "Tags") */
|
||||||
insertTagsLabel?: string
|
insertTagsLabel?: string
|
||||||
/** Extra content in Node menu (e.g. Export submenu for render nodes), before the separator */
|
/** Extra content in Node menu (e.g. Export submenu for render nodes), before the separator */
|
||||||
nodeMenuExtraContent?: React.ReactNode
|
nodeMenuExtraContent?: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NodeMenubar({ nodeId, nodeType, editInputsContent, insertTagsContent, insertTagsLabel = 'Tags', nodeMenuExtraContent }: Props) {
|
export function NodeMenubar({ nodeId, nodeType, editInputsContent, inputsMenuContent, insertTagsContent, insertMenuLabel = 'Insert', insertContentDirect, insertTagsLabel = 'Tags', nodeMenuExtraContent }: Props) {
|
||||||
const ctx = useContext(FlowContext)
|
const ctx = useContext(FlowContext)
|
||||||
const nodes = ctx?.nodes ?? []
|
const nodes = ctx?.nodes ?? []
|
||||||
const setNodes = ctx?.setNodes
|
const setNodes = ctx?.setNodes
|
||||||
@@ -108,12 +114,23 @@ export function NodeMenubar({ nodeId, nodeType, editInputsContent, insertTagsCon
|
|||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
</MenubarMenu>
|
</MenubarMenu>
|
||||||
{hasEdit && (
|
{inputsMenuContent != null && (
|
||||||
|
<MenubarMenu>
|
||||||
|
<MenubarTrigger className="px-1.5 py-0 text-xs" disabled={!hasConnectedNodes}>
|
||||||
|
Inputs
|
||||||
|
</MenubarTrigger>
|
||||||
|
<MenubarContent className="min-w-[12rem]">
|
||||||
|
{inputsMenuContent}
|
||||||
|
</MenubarContent>
|
||||||
|
</MenubarMenu>
|
||||||
|
)}
|
||||||
|
{hasEdit && (insertTagsContent != null || (editInputsContent != null && inputsMenuContent == null)) && (
|
||||||
<MenubarMenu>
|
<MenubarMenu>
|
||||||
<MenubarTrigger className="px-1.5 py-0 text-xs">
|
<MenubarTrigger className="px-1.5 py-0 text-xs">
|
||||||
Insert
|
{insertMenuLabel}
|
||||||
</MenubarTrigger>
|
</MenubarTrigger>
|
||||||
<MenubarContent className="min-w-[10rem]">
|
<MenubarContent className="min-w-[10rem]">
|
||||||
|
{inputsMenuContent == null && editInputsContent != null && (
|
||||||
<MenubarSub>
|
<MenubarSub>
|
||||||
<MenubarSubTrigger className="text-xs" disabled={!hasConnectedNodes}>
|
<MenubarSubTrigger className="text-xs" disabled={!hasConnectedNodes}>
|
||||||
Inputs
|
Inputs
|
||||||
@@ -122,7 +139,11 @@ export function NodeMenubar({ nodeId, nodeType, editInputsContent, insertTagsCon
|
|||||||
{editInputsContent}
|
{editInputsContent}
|
||||||
</MenubarSubContent>
|
</MenubarSubContent>
|
||||||
</MenubarSub>
|
</MenubarSub>
|
||||||
{insertTagsContent != null && (
|
)}
|
||||||
|
{insertTagsContent != null &&
|
||||||
|
(insertContentDirect ? (
|
||||||
|
insertTagsContent
|
||||||
|
) : (
|
||||||
<MenubarSub>
|
<MenubarSub>
|
||||||
<MenubarSubTrigger className="text-xs">
|
<MenubarSubTrigger className="text-xs">
|
||||||
{insertTagsLabel}
|
{insertTagsLabel}
|
||||||
@@ -131,7 +152,7 @@ export function NodeMenubar({ nodeId, nodeType, editInputsContent, insertTagsCon
|
|||||||
{insertTagsContent}
|
{insertTagsContent}
|
||||||
</MenubarSubContent>
|
</MenubarSubContent>
|
||||||
</MenubarSub>
|
</MenubarSub>
|
||||||
)}
|
))}
|
||||||
</MenubarContent>
|
</MenubarContent>
|
||||||
</MenubarMenu>
|
</MenubarMenu>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -599,7 +599,11 @@ export const RenderingNode = memo(function RenderingNode({ id, width, height }:
|
|||||||
|
|
||||||
<BaseNodeFooter>
|
<BaseNodeFooter>
|
||||||
<NodeFooterEdgeIndicators nodeId={id} nodeType="render">
|
<NodeFooterEdgeIndicators nodeId={id} nodeType="render">
|
||||||
{renderedContent ? (isSvgOutput ? 'Diagram' : 'Markdown') : error ? 'Error' : '—'}
|
{renderedContent
|
||||||
|
? `${isSvgOutput ? 'Diagram' : 'Markdown'} · ${renderedContent.length} chars`
|
||||||
|
: error
|
||||||
|
? 'Error'
|
||||||
|
: '—'}
|
||||||
</NodeFooterEdgeIndicators>
|
</NodeFooterEdgeIndicators>
|
||||||
</BaseNodeFooter>
|
</BaseNodeFooter>
|
||||||
</BaseNode>
|
</BaseNode>
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ export const VariableNode = memo(function VariableNode({ id, data }: Props) {
|
|||||||
</BaseNodeContent>
|
</BaseNodeContent>
|
||||||
|
|
||||||
<BaseNodeFooter>
|
<BaseNodeFooter>
|
||||||
<NodeFooterEdgeIndicators nodeId={id} nodeType="variable" />
|
<NodeFooterEdgeIndicators nodeId={id} nodeType="variable">
|
||||||
|
{`${valueType.charAt(0).toUpperCase() + valueType.slice(1)} · ${displayValue.length ? `${displayValue.length} chars` : 'none'}`}
|
||||||
|
</NodeFooterEdgeIndicators>
|
||||||
</BaseNodeFooter>
|
</BaseNodeFooter>
|
||||||
</BaseNode>
|
</BaseNode>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const PLANTUML_INSERT_BLOCKS: InsertBlockOrGroup[] = [
|
|||||||
{ label: 'Arrow', snippet: ' -> ' },
|
{ label: 'Arrow', snippet: ' -> ' },
|
||||||
{ label: 'Note', snippet: 'note right of ' },
|
{ label: 'Note', snippet: 'note right of ' },
|
||||||
{
|
{
|
||||||
label: 'Nunjucks',
|
label: 'Templating',
|
||||||
items: [
|
items: [
|
||||||
{ label: 'Variable {{ }}', snippet: '{{ }}' },
|
{ label: 'Variable {{ }}', snippet: '{{ }}' },
|
||||||
{ label: 'if / endif', snippet: '{% if %}\n \n{% endif %}' },
|
{ label: 'if / endif', snippet: '{% if %}\n \n{% endif %}' },
|
||||||
@@ -64,7 +64,7 @@ const MARKDOWN_INSERT_BLOCKS: InsertBlockOrGroup[] = [
|
|||||||
{ label: 'List item', snippet: '- ' },
|
{ label: 'List item', snippet: '- ' },
|
||||||
{ label: 'Blockquote', snippet: '> ' },
|
{ label: 'Blockquote', snippet: '> ' },
|
||||||
{
|
{
|
||||||
label: 'Nunjucks',
|
label: 'Templating',
|
||||||
items: [
|
items: [
|
||||||
{ label: 'Variable {{ }}', snippet: '{{ }}' },
|
{ label: 'Variable {{ }}', snippet: '{{ }}' },
|
||||||
{ label: 'if / endif', snippet: '{% if %}\n \n{% endif %}' },
|
{ label: 'if / endif', snippet: '{% if %}\n \n{% endif %}' },
|
||||||
|
|||||||
Reference in New Issue
Block a user