Skip to content

Custom Renderers

See the Renderers syntax page for grammar and semantics. This page covers the registration API for adding your own renderers to the validator and editor.

A Renderer declares:

  • name — the identifier users type after the alias pipe
  • arg_schema — a tuple of ArgSpec(type, required) entries that drive arg-count and arg-type validation
  • metadata — an optional freeform dict/map/object for application use; flyql never inspects its contents
  • diagnose(args, parsed_column) — an optional per-renderer hook returning Diagnostic[] for custom validation
from flyql.flyql_type import Type
from flyql.renderers import ArgSpec, Renderer, RendererRegistry
from flyql.columns import parse, diagnose
from flyql.core.validator import Diagnostic
from flyql.core.range import Range
class HrefRenderer(Renderer):
arg_schema = (ArgSpec(type=Type.String, required=True),)
@property
def name(self) -> str:
return "href"
@property
def metadata(self):
return {"html_safe": True}
def diagnose(self, arguments, parsed_column):
if arguments and "{{value}}" not in arguments[0]:
return [Diagnostic(
range=Range(0, 1),
message="href template should contain {{value}}",
severity="warning",
code="custom_href_no_placeholder",
)]
return []
registry = RendererRegistry()
registry.register(HrefRenderer())
cols = parse('url as link|href("/users/{{value}}")',
capabilities={"transformers": True, "renderers": True})
# ...then run the validator with both registries:
diags = diagnose(cols, schema, renderer_registry=registry)

For chain-level rules (e.g. “forbid href after truncate”) use set_diagnose:

def chain_rule(parsed_column, chain):
names = [r["name"] for r in chain]
if "truncate" in names and "href" in names:
if names.index("truncate") < names.index("href"):
return [Diagnostic(
range=Range(0, 1),
message="href cannot follow truncate",
severity="error",
code="chain_forbidden",
)]
return []
registry.set_diagnose(chain_rule)

The chain hook runs after per-renderer diagnose hooks and after the built-in unknown-name / arg-count / arg-type checks.

import (
flyql "github.com/iamtelescope/flyql/golang"
"github.com/iamtelescope/flyql/golang/columns"
"github.com/iamtelescope/flyql/golang/flyqltype"
"github.com/iamtelescope/flyql/golang/transformers"
)
type HrefRenderer struct{ columns.BaseRenderer }
func (HrefRenderer) Name() string { return "href" }
func (HrefRenderer) ArgSchema() []transformers.ArgSpec {
return []transformers.ArgSpec{{Type: flyqltype.String, Required: true}}
}
reg := columns.DefaultRendererRegistry()
_ = reg.Register(HrefRenderer{})
opts := columns.DiagnoseOptions{RendererRegistry: reg}
diags := columns.DiagnoseWithOptions(parsedColumns, schema, opts)
import { Renderer, RendererRegistry, ArgSpec } from 'flyql/renderers'
import { Type } from 'flyql'
import { parse, diagnose } from 'flyql/columns'
class HrefRenderer extends Renderer {
get name() { return 'href' }
get argSchema() { return [new ArgSpec(Type.String, true)] }
diagnose(args, col) {
if (args && args[0] && !args[0].includes('{{value}}')) {
return [{
range: { start: 0, end: 1 },
message: 'href template should contain {{value}}',
severity: 'warning',
code: 'custom_href_no_placeholder',
}]
}
return []
}
}
const registry = new RendererRegistry()
registry.register(new HrefRenderer())
const cols = parse('url as link|href("/users/{{value}}")',
{ transformers: true, renderers: true })
const diags = diagnose(cols, schema, null, registry)

The FlyqlColumns Vue component accepts a rendererRegistry prop. When supplied, the editor enables post-alias renderer parsing, emits renderer suggestions, and surfaces renderer diagnostics:

<template>
<FlyqlColumns
v-model="query"
:columns="schema"
:registry="transformerRegistry"
:renderer-registry="rendererRegistry"
/>
</template>

When rendererRegistry is omitted or null, renderer parsing is disabled entirely — users typing post-alias | see a parser-level rejection rather than unknown_renderer diagnostics on every keystroke. See Columns Component for the full prop reference.