UNPKG

jexl-extended

Version:

Extended grammar for Javascript Expression Language (JEXL)

162 lines (161 loc) 5.38 kB
/** * Monaco Editor Completion Provider for JEXL * This provides IntelliSense completion items without requiring Monaco as a dependency */ // Import completion docs directly (generated file) import { completionDocs } from './completion-docs.generated'; // Monaco CompletionItemKind enum values (to avoid Monaco dependency) export const CompletionItemKind = { Method: 0, Function: 1, Constructor: 2, Field: 3, Variable: 4, Class: 5, Struct: 6, Interface: 7, Module: 8, Property: 9, Event: 10, Operator: 11, Unit: 12, Value: 13, Constant: 14, Enum: 15, EnumMember: 16, Keyword: 17, Text: 18, Color: 19, File: 20, Reference: 21, Customcolor: 22, Folder: 23, TypeParameter: 24, User: 25, Issue: 26, Snippet: 27 }; export function createJexlCompletionItems(type, filter) { let filteredDocs = type ? completionDocs.filter((doc) => doc.type === type) : completionDocs; const items = []; const filterLower = filter ? filter.toLowerCase() : ""; for (const doc of filteredDocs) { const kind = doc.type === "function" ? CompletionItemKind.Function : CompletionItemKind.Method; if (!filter || doc.label.toLowerCase().startsWith(filterLower)) { items.push({ label: doc.label, kind, insertText: doc.insertText, insertTextRules: 4, documentation: doc.documentation, detail: doc.detail, }); } if (doc.aliases) { for (const alias of doc.aliases) { if ((!filter || alias.toLowerCase().startsWith(filterLower)) && alias !== doc.label) { items.push({ label: alias, kind, insertText: doc.insertText.replace(doc.label, alias), insertTextRules: 4, documentation: doc.documentation, detail: doc.detail, }); } } } } // Remove duplicates by label const seen = new Set(); return items.filter((item) => { if (seen.has(item.label)) return false; seen.add(item.label); return true; }); } export function createJexlFunctionItems() { return createJexlCompletionItems("function"); // legacy: no filter } export function createJexlTransformItems() { return createJexlCompletionItems("transform"); // legacy: no filter } export function getJexlCompletionDoc(functionName, preferredType) { // Find all matches for the function name const matches = completionDocs.filter(doc => doc.label === functionName || doc.name === functionName || doc.aliases?.includes(functionName)); if (matches.length === 0) { return undefined; } // If we have a preferred type, try to find that first if (preferredType) { const preferredMatch = matches.find(doc => doc.type === preferredType); if (preferredMatch) { return preferredMatch; } } // Otherwise return the first match return matches[0]; } export function getOperatorDoc(operator) { const operators = createJexlOperators(); const operatorItem = operators.find(op => op.label === operator); if (operatorItem) { return { label: operatorItem.label, documentation: operatorItem.documentation || '', detail: operatorItem.detail || 'JEXL Operator' }; } return undefined; } export function createJexlKeywords() { // Accurate JEXL keywords based on actual grammar const keywords = ['true', 'false', 'null', 'undefined', 'in']; return keywords.map(keyword => ({ label: keyword, kind: CompletionItemKind.Keyword, insertText: keyword, documentation: `JEXL keyword: ${keyword}`, detail: 'JEXL Keyword' })); } export function createJexlOperators() { // Accurate JEXL operators based on actual grammar const operators = [ { label: '|', desc: 'Transform pipe operator' }, { label: '==', desc: 'Equality comparison' }, { label: '!=', desc: 'Inequality comparison' }, { label: '>', desc: 'Greater than' }, { label: '<', desc: 'Less than' }, { label: '>=', desc: 'Greater than or equal' }, { label: '<=', desc: 'Less than or equal' }, { label: '&&', desc: 'Logical AND' }, { label: '||', desc: 'Logical OR' }, { label: '!', desc: 'Logical NOT' }, { label: 'in', desc: 'Membership test' }, { label: '+', desc: 'Addition' }, { label: '-', desc: 'Subtraction' }, { label: '*', desc: 'Multiplication' }, { label: '/', desc: 'Division' }, { label: '//', desc: 'Floor division' }, { label: '%', desc: 'Modulus' }, { label: '^', desc: 'Exponentiation' }, { label: '?', desc: 'Conditional operator' }, { label: ':', desc: 'Conditional separator' } ]; return operators.map(op => ({ label: op.label, kind: CompletionItemKind.Operator, insertText: op.label, documentation: op.desc, detail: 'JEXL Operator' })); }