Enhance fcTemplateLang Schema with New Style Attributes and Placeholder Support
- Added 'margin', 'header', and 'footer' to the list of style attributes, allowing for more flexible styling options.
- Updated the logic for 'vertical', 'header', and 'footer' to include boolean values in their attribute definitions.
- Introduced pagination placeholders ('!pageNumber' and '!totalPages') to support dynamic content in templates.
- Implemented a completion source function for placeholders, enhancing user experience by providing context-aware suggestions.
This commit is contained in:
parent
eea7e1f724
commit
c9751dd5ef
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user