diff --git a/src/core/formDefinitionSchema.ts b/src/core/formDefinitionSchema.ts index 55e9441d..ff3eb919 100644 --- a/src/core/formDefinitionSchema.ts +++ b/src/core/formDefinitionSchema.ts @@ -22,6 +22,7 @@ import { } from "valibot"; import { AllFieldTypes, FormDefinition } from "./formDefinition"; import { findFieldErrors } from "./findInputDefinitionSchema"; +import { ParsedTemplateSchema } from "./template/templateSchema"; /** * Here are the core logic around the main domain of the plugin, @@ -176,6 +177,7 @@ const FormDefinitionV1Schema = merge([ object({ version: literal("1"), fields: FieldListSchema, + template: optional(ParsedTemplateSchema) }), ]); // This is the latest schema. diff --git a/src/core/templateParser.test.ts b/src/core/template/templateParser.test.ts similarity index 100% rename from src/core/templateParser.test.ts rename to src/core/template/templateParser.test.ts diff --git a/src/core/templateParser.ts b/src/core/template/templateParser.ts similarity index 80% rename from src/core/templateParser.ts rename to src/core/template/templateParser.ts index eae08944..570bdc2b 100644 --- a/src/core/templateParser.ts +++ b/src/core/template/templateParser.ts @@ -1,11 +1,13 @@ import * as E from 'fp-ts/Either'; +import * as St from 'fp-ts/String' import * as P from 'parser-ts/Parser' import { run } from 'parser-ts/code-frame' import * as C from 'parser-ts/char' import * as S from 'parser-ts/string' -import { A, Either, O, pipe } from '@std'; -type TemplateText = { _tag: 'text', value: string } -type TemplateVariable = { _tag: 'variable', value: string } +import * as A from 'fp-ts/Array' +import { Either, O, pipe } from '@std'; +import { TemplateText, TemplateVariable } from './templateSchema'; +import { absurd } from 'fp-ts/function'; type Token = TemplateText | TemplateVariable export type ParsedTemplate = Token[]; @@ -84,3 +86,20 @@ export function templateError(parsedTemplate: ReturnType): ) ) } + +function tokenToString(token: Token): string { + const tag = token._tag + switch (tag) { + case 'text': return token.value + case 'variable': return `{{${token.value}}}` + default: + return absurd(tag) + } +} + +export function parsedTemplateToString(parsedTemplate: ParsedTemplate): string { + return pipe( + parsedTemplate, + A.foldMap(St.Monoid)(tokenToString) + ) +} diff --git a/src/core/template/templateSchema.ts b/src/core/template/templateSchema.ts new file mode 100644 index 00000000..7bf78720 --- /dev/null +++ b/src/core/template/templateSchema.ts @@ -0,0 +1,16 @@ +import { Output, array, literal, object, string, union } from "valibot"; + +const TemplateTextSchema = object({ + _tag: literal("text"), + value: string(), +}); + +const TemplateVariableSchema = object({ + _tag: literal("variable"), + value: string(), +}); + +export const ParsedTemplateSchema = array(union([TemplateTextSchema, TemplateVariableSchema])) + +export type TemplateText = Output; +export type TemplateVariable = Output; diff --git a/src/views/FormBuilder.svelte b/src/views/FormBuilder.svelte index 836fe944..dcaa49ce 100644 --- a/src/views/FormBuilder.svelte +++ b/src/views/FormBuilder.svelte @@ -18,6 +18,10 @@ import { pipe } from "fp-ts/lib/function"; import { A } from "@std"; import Tabs from "./components/Tabs.svelte"; + import { + ParsedTemplate, + parsedTemplateToString, + } from "src/core/template/templateParser"; export let definition: EditableFormDefinition = { title: "", @@ -116,6 +120,9 @@ if (!isValidFormDefinition(definition)) return; onSubmit(definition); }; + function saveTemplate(template: ParsedTemplate) { + onSubmit({ ...definition, template }); + } const handlePreview = () => { if (!isValidFormDefinition(definition)) return; console.log("preview of", definition); @@ -128,7 +135,14 @@
{#if currentTab === "template"}
- +
{:else}
diff --git a/src/views/components/TemplateEditor.svelte b/src/views/components/TemplateEditor.svelte index 9b220a8f..e3d98e15 100644 --- a/src/views/components/TemplateEditor.svelte +++ b/src/views/components/TemplateEditor.svelte @@ -4,11 +4,11 @@ parseTemplate, templateError, templateVariables, - } from "src/core/templateParser"; + } from "src/core/template/templateParser"; import Code from "./Code.svelte"; import { E, pipe } from "@std"; - let templateString = ""; + export let templateString: string; export let formName: string; export let fieldNames: string[]; export let saveTemplate: (template: ParsedTemplate) => void; diff --git a/tsconfig.json b/tsconfig.json index f6c710cf..7a041f12 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -47,17 +47,41 @@ "A": { "importPath": "fp-ts/Array" }, + "R": { + "importPath": "fp-ts/Record" + }, + "RA": { + "importPath": "fp-ts/ReadonlyArray" + }, + "RE": { + "importPath": "fp-ts/ReaderEither" + }, + "RIO": { + "importPath": "fp-ts/ReaderIO" + }, + "RNEA": { + "importPath": "fp-ts/ReadonlyNonEmptyArray" + }, + "RT": { + "importPath": "fp-ts/ReaderTask" + }, + "RTE": { + "importPath": "fp-ts/ReaderTaskEither" + }, + "S": { + "importPath": "fp-ts/string" + }, "T": { "importPath": "fp-ts/Task" }, "TE": { "importPath": "fp-ts/TaskEither" }, - "R": { - "importPath": "fp-ts/Record" + "TO": { + "importPath": "fp-ts/TaskOption" }, - "RA": { - "importPath": "fp-ts/ReadonlyArray" + "TU": { + "importPath": "fp-ts/Tuple" }, } }