accordproject / markdown-transform

Parse and transform markdown text, including TemplateMark markdown templates
Apache License 2.0
73 stars 50 forks source link

Support for tables in the Markdown #196

Open jeromesimeon opened 4 years ago

jeromesimeon commented 4 years ago

Is your feature request related to a problem? Please describe. It's not related to a problem, it's related to a feature. Namely having an agreed upon markdown notation for tables which are common in contracts.

Describe the solution you'd like A user-friendly way to describe tables in the markdown we support.

Describe alternatives you've considered This could be achieved in a number of ways:

Additional context

mttrbrts commented 4 years ago

I have been thinking about the GSoC project for DMN, and if this is somehow related.

For example, a DMN Decision Table in CiceroMark.

We could go in a few different directions here:

  1. Support for base tables is a prerequisite for DMN Decision Tables, and we allow DMN / FEEL expressions within table cells as a kind of computed parameter
  2. We support both structural tables (as in GFM), and DMN Decision Tables as separate DOM nodes.
jeromesimeon commented 4 years ago

I have been thinking about the GSoC project for DMN, and if this is somehow related.

For example, a DMN Decision Table in CiceroMark.

We could go in a few different directions here:

  1. Support for base tables is a prerequisite for DMN Decision Tables, and we allow DMN / FEEL expressions within table cells as a kind of computed parameter
  2. We support both structural tables (as in GFM), and DMN Decision Tables as separate DOM nodes.

I like this idea. I would make sure to distinguish tables in the instance contract text or tables in the template grammar (I think the DMN would be the latter? so more an extension to our template).

An example to crystallise those thoughts would be great!

mttrbrts commented 4 years ago

image

Using this XML example from https://camunda.com/dmn/

Season How many guests Dish
"Fall" <= 8 "Spareribs"
"Winter" <= 8 "Roastbeef"
"Spring" <= 4 "Dry Aged Gourmet Steak"
"Spring" [5..8] "Steak"
"Fall","Winter","Summer" > 8 "Spareribs"
"Summer" "Light Salad and a nice Steak"
| #dmn:input Season season string | #dmn:input "How many guests" guestCount integer | #dmn:output Dish desiredDish string | 
| --- | --- | --- |
| "Fall" | <= 8 | "Spareribs" |
| "Winter" | <= 8 | "Roastbeef" |
| "Spring" | <= 4 | "Dry Aged Gourmet Steak" |
| "Spring" | [5..8] | "Steak" |
| "Fall","Winter","Summer" | > 8 | "Spareribs" |
| "Summer" | | "Light Salad and a nice Steak" |

Where the presence of #dmn block notation in every header indicates that this table should be interpreted as a DMN decision table. For this simple example at least we could then generate the DMN XML representation to feed into a DMN engine.

dselman commented 4 years ago

Interesting! I'd imagined that DMN would sit at the implementation side of the business logic of a template (as another form of Ergo function, parameterised using contract data), rather than directly in the text of the contract, but this opens intriguing possibilities for negotiating complex contract logic, rather than just variable values.

mttrbrts commented 4 years ago

Thinking further, I'm not sure that DMN is necessary here, we already have an expression language in the form of Ergo, and compiling to then parsing DMN XML when editing could be expensive.

I think that I'm advocating a "Decision Table" concept in Cicero which is a combination of computed Ergo expressions and tables, plus possibly a new list block type to allow dynamic rows.

jeromesimeon commented 4 years ago

@mttrbrts We could probably investigate that direction. A few questions.

  1. Where are the variables in that table above. Can I assume the column names would always be the variables? (we need to know what to compare against when an entry says e.g., <=8) Can expressions refer to variables explicitly or to variables in other columns?
  2. I don't completely understand the data flow. What is the output? How is the table being used? I'm assuming the whole table is printed in the contract? How do I call the table for a given product? is that part of the post-signature logic?
  3. Should we add display names for variables in the CiceroMark spec? (e.g., "How many guests" vs guestCount
  4. Do we also want some kind of compatibility with the DMN spec? (because people might have existing code, because someone might want to use a DMN editor?) For that we would need indeed some kind of mapping between the DMN table and the underlying Ergo (which likely have somewhat different syntax and semantics).

I think we could try and come up with something for 1.2.3. first, then 4. becomes a compilation problem from DMN to CiceroMark+Tables or pure Ergo.

PS. If we can refer to other variables, there are interesting questions around scoping. Can an expression refer to a variable in another part of the contract? e.g.,


This is a sales contract, with a commission of {{commissionAmount}}

| #dmn:input Season season string | #dmn:input "How many guests" guestCount integer | #dmn:output Dish desiredDish string | 
| --- | --- | --- |
| "Fall" | <= 8 + commissionAmount | "Spareribs" |
| "Winter" | <= 8 + commissionAmount | "Roastbeef" |
| "Spring" | <= 4 + commissionAmount | "Dry Aged Gourmet Steak" |
| "Spring" | [5..8] | "Steak" |
| "Fall","Winter","Summer" | > 8 + commissionAmount | "Spareribs" |
| "Summer" | | "Light Salad and a nice Steak" |
mttrbrts commented 4 years ago

Typically with decision tables, they operate like functions with the input context being all of the input columns, and they produce the output in the output columns. In Cicero, we could equate this with Request and Response models respectively.

However, I could imagine that the expressions could include variables from the template model too.

For example:

| #dmn:input Season season string | ... | 
| --- | --- |
| "Fall" | ... |

means when request.season === "Fall"... set response.desiredDish = "Spareribs"

But we could also do something like ...

| #dmn:input Season season string | ... | 
| --- | --- |
| {{myContractVariable}} | ... |

For 3., I always thought that we would accomplish this with model annotations. Perhaps we should design some conventions or built-in annotations, e.g. for display name, prompt question ?

  1. I'm vacillating on this. I think some use cases could help.
jeromesimeon commented 4 years ago

Typically with decision tables, they operate like functions with the input context being all of the input columns, and they produce the output in the output columns. In Cicero, we could equate this with Request and Response models respectively.

However, I could imagine that the expressions could include variables from the template model too.

For example:

| #dmn:input Season season string | ... | 
| --- | --- |
| "Fall" | ... |

means when request.season === "Fall"... set response.desiredDish = "Spareribs"

But we could also do something like ...

| #dmn:input Season season string | ... | 
| --- | --- |
| {{myContractVariable}} | ... |

For 3., I always thought that we would accomplish this with model annotations. Perhaps we should design some conventions or built-in annotations, e.g. for display name, prompt question ?

  1. I'm vacillating on this. I think some use cases could help.

~Great. I think we are on the same page. To clarify:~

~Is that also your understanding?~

Maybe I need to digest this: "Typically with decision tables, they operate like functions with the input context being all of the input columns, and they produce the output in the output columns."

Maybe those are right?:

  1. The table is in the contract template
  2. The same table is in the contract instance?
  3. The table is a function (clause in Ergo) taking a Request containing variables from the input columns and returning a Response containing the output columns?
mttrbrts commented 4 years ago

Yes, I think that all of those 3 points are correct

jeromesimeon commented 4 years ago

Yes, I think that all of those 3 points are correct

One more question: in DMN can there be more than one output column?

mttrbrts commented 4 years ago

I believe so, but only with a complex object

OliverTod commented 3 years ago

My understanding of this might be overly simplistic (sorry!), but I would have thought that most of the benefits of a DMN table (as set out above) can be easily achieved using the existing framework of variables and match statements.

That is, in the template/instance, you could simply have a table that looks like this: | {{variable name}} | {{variable value}} | | {{variable2 name}} | {{variable2 value}} | and then use 'match' statements in the ergo to dictate the logic.

In my experience, most contracts use tables for the relatively simple purpose of defining variables/values, setting out prices or aiding readability.

If this is the case, then support for the simplest possible table structure (I like the look of the github flavoured markdown syntax) would be a good first step.

dselman commented 2 years ago

@jeromesimeon have you got a link to the markdown table plugin that you mentioned we could use?