testmark-go

More readme; and, parsing recommendations document.

commit d7ff0980bf5177c1b0fc4834f762bbdf99f89388 · parent c6a1fb067e · browse this tree
Eric Myhre, 2021-08-23 11:50:57 UTC

diff --git a/README.md b/README.md
index 48a3b53..3a3b71f 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,14 @@ Your markdown documents can also be testmark documents!
 
 Testmark data is contained in a markdown codeblock -- you know, the things that start and end with triple-backticks.
 
+Testmark data is labled by a markdown comment.
+
+This means you can easily embed large blocks of data in a markdown file,
+and give them whatever label is appropriate,
+and do this seamlessly in a document you're also writing for a human audience.
+
+This makes for great development of test fixtures, specs, and documentation, all in one.
+
 ### testmark format by example
 
 You see markdown code blocks all the time.  They render like this:
@@ -72,9 +80,19 @@ The comment looks like this:
 ... and then the triple-backticks go right after that.
 Data follows until the next line starting with triple-backticks, as is usual in markdown.
 
+So, in total, it looks like this:
+
+```
+	[testmark]:# (the-data-name-goes-here)
+	```text
+	this is your data block
+	as big as you like
+	```
+```
+
 That's it.
 
-Check out the [testdata/example.md](testdata/example.md) file for another example.
+Check out the [testdata/example.md](testdata/example.md) file (and other files in that directory) for more examples.
 Be sure to mind the [raw form of the file](https://raw.githubusercontent.com/warpfork/go-testmark/master/testdata/example.md) too.
 
 ### the purpose of testmark
@@ -109,6 +127,11 @@ and now your documentation misleads users, and adoption drops and frustration ri
 
 tl;dr: deduplicate the work of spec fixtures and docs, both saving time, and getting more confident in the results, simultaneously.
 
+### parsing testmark is easy
+
+See [README_parsing](README_parsing.md) if you would like to write a testmark parser in another language.
+It's _extremely_ straightforward.
+
 
 This is go-testmark
 -------------------
diff --git a/README_parsing.md b/README_parsing.md
new file mode 100644
index 0000000..b1f9b95
--- /dev/null
+++ b/README_parsing.md
@@ -0,0 +1,100 @@
+Parsing Testmark
+================
+
+Parsing Testmark is extremely easy.
+
+There are two major roads you can take:
+
+1. Use a full-on markdown parser -- then only pluck out the data you need.
+2. Use a very (very!) simple parser that is sufficient to recognize testmark data within markdown.
+
+We actually recommend [Option 2](#option-2-write-a-testmark-focused-parser).
+Simple is better.
+
+
+Option 1: use a full-on markdown parser
+---------------------------------------
+
+Of course, since testmark is "just markdown",
+if you are working in a language that already has a suitable markdown parsing library,
+you can use that.
+
+You need to look for two things:
+
+1. markdown comment lines
+	- (which, if the library you're using doesn't talk about that explicitly, might also be referred to as "link labels")
+	- which have the label of "testmark"
+2. ...which are immediately followed by a code block.
+
+We won't spent any more time talking about how do actually do that in this document, though,
+because most of what you'll need to figure out is specific to the markdown library you use.
+
+We also don't really actually recommend this road at all.
+You can probably build something that's:
+
+- faster,
+- has fewer dependencies,
+- is equally correct,
+- easier to debug,
+- and has an easier, more reliable way to support "patching"
+
+... by going with [Option 2](#option-2-write-a-testmark-focused-parser): writing a simple parser focused on testmark alone.
+
+
+Option 2: write a testmark-focused parser
+-----------------------------------------
+
+It's extremely simple to build a direct testmark-focused parser --
+the only features we need to parse are line-break delimited,
+so the parser is both easy and extremely fool-proof to implement.
+
+(We _don't_ need to parse most of markdown in order to find the testmark elements!)
+
+Because every piece of data which is important to parse starts exactly on the beginning of a line,
+we can split the document into lines first, and then parse each line in a very direct way.
+
+- Split document into lines.
+- For each line: look for lines starting with triple-backticks.  These begin or end codeblocks.
+	- Store a state toggle for whether you're in a codeblock.  Do not parse lines within a codeblock.
+	- ... except to look for the end of the codeblock, which is another triple-backtick.
+- For each line not in a codeblock: if it starts with `[testmark]:# ` -- it may be a testmark block starting.
+- If the next line is the start of a codeblock, it's definitely a testmark block.
+- That's it.
+
+See how easy that was?
+
+There's a couple more details you should also mind:
+
+- The testmark comment line should continue with `(`, contain some text, and end in `)`.
+	- If it does not, you should notify the user of a funny thing here, and ignore it.
+	- The contained text, up to the first element of whitespace, is the testmark block label.
+	- Any content after the whitespace is currently ignored (but considered reserved for potential future use).
+- The testmark comment line must *immediately* precede a codeblock.
+	- If there is no codeblock after a testmark comment line, you should notify the user of a funny thing here, and ignore it.
+- Codeblocks start lines can contain some test after the triple-backtick.  This block tag is not part of testmark, but you may wish to know it's there.
+	- You can ignore it completely.  It usually contains a syntax rendering hint (this is a feature of GFM, a common markdown extension).
+	- Some testmark libraries detect this field, and allow it to be set during patch operations, but this is not considered a required feature of testmark.
+
+You can see a golang implementation of this in [read.go](read.go) if the example is helpful.
+The complete parser is less than 100 lines, and many of them are comments.
+
+### patching
+
+If you wish to support patching operations on a testmark document, this is very straightfoward by extending the above:
+when splitting the document into lines, just... remember that, and remember the line number where all the testmark hunks start and end.
+This information will be sufficient to enable patching.
+
+Now, when replacing a testmark data hunk, simply:
+
+- Emit all the lines of the original document, up until the testmark data hunk started;
+- Now serialize and emit the new testmark data hunk...
+	- One comment line
+	- One codeblock opener line
+	- All the user-specified content body lines
+	- One codeblock closer line
+- Emit all the lines of the original document, starting at the line number after the old testmark data ended.
+
+This is a very nice approach because we have (again) completely avoided parsing markdown,
+and thus the operations have been very simple, very fast, and very foolproof.
+This algorithm works exactly correctly no matter what other markdown extensions people may be using in their documents,
+and will never rewrite anything except the testmark data blocks, and thus follows "the principle of least surprise" very well.