import type { CompleteEvent } from "../../plug-api/types.ts"; import { datastore, events } from "@silverbulletmd/silverbullet/syscalls"; import type { AttributeCompleteEvent, AttributeCompletion, } from "../index/attributes.ts"; import { attributeCompletionsToCMCompletion } from "./snippet.ts"; export async function templateAttributeComplete(completeEvent: CompleteEvent) { // Check if we're in a query, block or template context const fencedParent = completeEvent.parentNodes.find((node) => node.startsWith("FencedCode:template") ); if (!fencedParent) { return null; } const attributeMatch = /(^|[^{])\{\{(\w*)$/.exec(completeEvent.linePrefix); if (!attributeMatch) { return null; } let allCompletions: any[] = []; // Function completions const functions = await datastore.listFunctions(); allCompletions = functions.map((name) => ({ label: name, apply: name, detail: "function", })); // Attribute completions const completions = (await events.dispatchEvent( `attribute:complete:_`, { source: "", prefix: attributeMatch[2], } as AttributeCompleteEvent, )).flat() as AttributeCompletion[]; allCompletions = allCompletions.concat( attributeCompletionsToCMCompletion(completions), ); return { from: completeEvent.pos - attributeMatch[2].length, options: allCompletions, }; } export function templateVariableComplete(completeEvent: CompleteEvent) { // Check if we're in a query, block or template context const fencedParent = completeEvent.parentNodes.find((node) => node.startsWith("FencedCode:template") ); if (!fencedParent) { return null; } // Find a @ inside of a {{ const variableMatch = /\{\{[^}]*@(\w*)$/.exec(completeEvent.linePrefix); if (!variableMatch) { return null; } let allCompletions: any[] = []; const regexp = /\s+@(\w+)\s+(=|in)\s+/g; const allVariables = new Set(); const matches = fencedParent.matchAll(regexp); for (const match of matches) { allVariables.add(match[1]); } allVariables.add("page"); allVariables.add("config"); allCompletions = allCompletions.concat( [...allVariables].map((key) => ({ label: `@${key}`, apply: key, detail: "variable", })), ); return { from: completeEvent.pos - variableMatch[1].length, options: allCompletions, }; }