diff --git a/src/codemirror/fcTemplateLang/schema.js b/src/codemirror/fcTemplateLang/schema.js index c7b9e192..ba84d953 100644 --- a/src/codemirror/fcTemplateLang/schema.js +++ b/src/codemirror/fcTemplateLang/schema.js @@ -3,8 +3,11 @@ * Mirrors custom elements / style attrs handled in farmcontrol-ws TemplateManager. */ +import { syntaxTree } from '@codemirror/language' + const styleAttrs = [ 'padding', + 'margin', 'width', 'height', 'minWidth', @@ -17,6 +20,8 @@ const styleAttrs = [ 'border', 'borderRadius', 'vertical', + 'header', + 'footer', 'grow', 'shrink', 'color', @@ -48,7 +53,9 @@ const alignValues = [ export const fcTemplateAttributes = [ ...styleAttrs.map((name) => { const attr = { name, global: true } - if (name === 'vertical') attr.values = ['true', 'false'] + if (name === 'vertical' || name === 'header' || name === 'footer') { + attr.values = ['true', 'false'] + } if (name === 'justify') attr.values = justifyValues if (name === 'align') attr.values = alignValues if (name === 'textAlign') { @@ -141,6 +148,69 @@ export const fcEmailTemplateHelpers = { } } +/** Pagination placeholders replaced after layout (`!pageNumber`, `!totalPages`). */ +export const fcTemplatePlaceholders = [ + { + name: '!pageNumber', + detail: 'Current page number' + }, + { + name: '!totalPages', + detail: 'Total page count' + } +] + +export function placeholderCompletionSource() { + const options = fcTemplatePlaceholders.map((placeholder) => ({ + label: placeholder.name, + apply: placeholder.name, + type: 'variable', + detail: placeholder.detail + })) + + return (context) => { + if (isPlaceholderBlockedContext(context.state, context.pos)) { + return null + } + + const before = context.state.sliceDoc(Math.max(0, context.pos - 48), context.pos) + const match = before.match(/![a-zA-Z]*$/) + if (!match) { + return null + } + + return { + from: context.pos - match[0].length, + options + } + } +} + +function isPlaceholderBlockedContext(state, position) { + let node = syntaxTree(state).resolveInner(position, -1) + + while (node) { + if ( + node.name === 'AttributeValue' || + node.name === 'AttributeName' || + node.name === 'Attribute' || + node.name === 'OpenTag' || + node.name === 'CloseTag' || + node.name === 'StartTag' || + node.name === 'TagName' || + node.name === 'JavascriptExpression' || + node.name === 'Scriptlet' || + node.name === 'Output' || + node.name === 'Comment' + ) { + return true + } + node = node.parent + } + + return false +} + export const fcTemplateHelpers = fcDocumentTemplateHelpers export function getFcTemplateHelpers(templateType) {