summaryrefslogtreecommitdiff
path: root/subplot.md
diff options
context:
space:
mode:
Diffstat (limited to 'subplot.md')
-rw-r--r--subplot.md789
1 files changed, 538 insertions, 251 deletions
diff --git a/subplot.md b/subplot.md
index 0901133..76e36f2 100644
--- a/subplot.md
+++ b/subplot.md
@@ -20,20 +20,20 @@ document.
We define the various concepts relevant to Subplot as follows:
-* **Acceptance criteria**: What the stakeholders require of the system
+* **Acceptance criteria:** What the stakeholders require of the system
for them to be happy with it and use it.
-* **Stakeholder**: Someone with a keen interest in the success of a
+* **Stakeholder:** Someone with a keen interest in the success of a
system. They might be a paying client, someone who uses the system,
or someone involved in developing the system. Depending on the
system and project, some stakeholders may have a bigger say than
others.
-* **Acceptance test**: How stakeholders verify that the system
+* **Acceptance test:** How stakeholders verify that the system
fulfills the acceptance criteria, in an automated way. Some criteria
may not be possible to verify automatically.
-* **Scenario**: In Subplot, the acceptance criteria are written as
+* **Scenario:** In Subplot, the acceptance criteria are written as
freeform prose, with diagrams, etc. The scenarios, which are
embedded blocks of Subplot scenario language, capture the mechanisms
of verifying that criteria are met - the acceptance tests - showing
@@ -63,7 +63,7 @@ technical text that's aimed at all your stakeholders.
## Subplot architecture
Subplot reads an input document, in Markdown, and generates a typeset
-output document, as PDF or HTML, for all stakeholders to understand.
+output document, as HTML, for all stakeholders to understand.
Subplot also generates a test program, in Python, that verifies the
acceptance criteria are met, for developers and testers and auditors
to verify the system under test meets its acceptance criteria. The
@@ -85,9 +85,6 @@ impl [shape=box];
subplot [label="Subplot"];
subplot [shape=ellipse];
-pdf [label="foo.pdf \n PDF (generated)"]
-pdf [shape=note];
-
html [label="foo.html \n HTML (generated)"]
html [shape=note];
@@ -100,20 +97,13 @@ report [shape=note];
md -> subplot;
bindings -> subplot;
impl -> subplot;
-subplot -> pdf;
subplot -> html;
subplot -> testprog;
testprog -> report;
}
```
-[Pandoc]: https://pandoc.org/
-
-Subplot uses the [Pandoc][] software for generating PDF and HTML
-output documents. In fact, any output format supported by Pandoc can
-be requested by the user. Depending on the output format, Pandoc may
-use, for example, LaTeX. Subplot interprets parts of the Markdown
-input file itself.
+Subplot generated HTML itself.
Subplot actually consists mainly of two separate programs:
**subplot docgen** for generating output documents, and **subplot codegen** for
@@ -140,9 +130,6 @@ docgen [shape=ellipse];
codegen [label="subplot codegen"];
codegen [shape=ellipse];
-pdf [label="foo.pdf \n PDF (generated)"]
-pdf [shape=note];
-
html [label="foo.html \n HTML (generated)"]
html [shape=note];
@@ -157,7 +144,6 @@ bindings -> docgen;
md -> codegen;
bindings -> codegen;
impl -> codegen;
-docgen -> pdf;
docgen -> html;
codegen -> testprog;
testprog -> report;
@@ -315,56 +301,56 @@ tests for Subplot](#acceptance).
Each requirement here is given a unique mnemonic id for easier
reference in discussions.
-**UnderstandableTests**
+* **UnderstandableTests**
-: Acceptance tests should be possible to express in a way that's
- easily understood by all stakeholders, including those who are
- not software developers.
+ Acceptance tests should be possible to express in a way that's
+ easily understood by all stakeholders, including those who are not
+ software developers.
_Done_ but requires the Subplot document to be written with care.
-**EasyToWriteDocs**
+* **EasyToWriteDocs**
-: The markup language for writing documentation should be easy to
+ The markup language for writing documentation should be easy to
write.
_Done_ by using Markdown.
-**AidsComprehension**
+* **AidsComprehension**
-: The formatted human-readable documentation should use good layout
+ The formatted human-readable documentation should use good layout
and typography to enhance comprehension.
- _In progress_ — typesetting via Pandoc works, but may need
- review and improvement.
+ _In progress_ — we currently only output HTML, but may add
+ PDF output back later.
-**CodeSeparately**
+* **CodeSeparately**
-: The code to implement the acceptance criteria should not be
+ The code to implement the acceptance criteria should not be
embedded in the documentation source, but be in separate files.
This makes it easier to edit without specialised tooling.
_Done_ by keeping scenario step implementations in a separate
file.
-**AnyProgammingLanguage**
+* **AnyProgammingLanguage**
-: The developers implementing the acceptance tests should be free to
+ The developers implementing the acceptance tests should be free to
use a language they're familiar and comfortable with. Subplot
should not require them to use a specific language.
_Not done_ — only Python supported at the moment.
-**FastTestExecution**
+* **FastTestExecution**
-: Executing the acceptance tests should be fast.
+ Executing the acceptance tests should be fast.
_Not done_ — the generated Python test program is simplistic
and linear.
-**NoDeployment**
+* **NoDeployment**
-: The acceptance test tooling should assume the system under test is
+ The acceptance test tooling should assume the system under test is
already deployed and available. Deploying is too big of a problem
space to bring into the scope of acceptance testing, and there are
already good tools for deployment.
@@ -372,9 +358,9 @@ reference in discussions.
_Done_ by virtue of letting those who implement the scenario steps
worry about it.
-**MachineParseableResults**
+* **MachineParseableResults**
-: The tests should produce a machine parseable result that can be
+ The tests should produce a machine parseable result that can be
archived, post-processed, and analyzed in ways that are of
interest to the project using Subplot. For example, to see trends
in how long tests take, how often tests fail, to find regressions,
@@ -387,16 +373,13 @@ reference in discussions.
Subplot reads three input files, each in a different format:
-* The document file, which uses the Markdown dialects understood by
- Pandoc.
+* The document file in [GitHub Flavored Markdown](https://github.github.com/gfm/).
* The bindings file, in YAML.
* The functions file, in Bash or Python.
Subplot interprets marked parts of the input document
-specially. It does this via the Pandoc abstract syntax tree, rather
-than text manipulation, and thus anything that Pandoc understands is
-understood by Subplot. We will not specify Pandoc's dialect of
-Markdown here, only the parts Subplot pays attention to.
+specially. These are fenced code blocks tagged with the `sceanrio`,
+`file`, or `example` classes.
## Scenario language
@@ -521,14 +504,9 @@ will deal with formatting that nicely for you.
## Document markup
-[Pandoc]: https://pandoc.org/
+Subplot parses Markdown input files using GitHub-flavored Markdown.
-Subplot uses [Pandoc][], the universal document converter, to parse
-the Markdown file, and thus understands the variants of Markdown that
-Pandoc supports. This includes traditional Markdown, CommonMark, and
-GitHub-flavored Markdown.
-
-[fenced code blocks]: https://pandoc.org/MANUAL.html#fenced-code-blocks
+[fenced code blocks]: https://github.github.com/gfm/#fenced-code-blocks
Subplot extends Markdown by treating certain certain tags for [fenced
code blocks][] specially. A scenario, for example, would look like
@@ -550,6 +528,11 @@ block for the test program. Snippets under the same heading belong
together; the next heading of the same or a higher level ends the
scenario.
+For `scenario` blocks you may not use any attributes. All attributes
+are reserved for Subplot. Subplot doesn't define any attributes yet,
+but by reserving all of them, it can add them later without it being
+a breaking change.
+
For embedding test data files in the Markdown document, Subplot
understands the `file` tag:
@@ -561,11 +544,7 @@ This data is accessible to the test program as 'filename'.
The `.file` attribute is necessary, as is the identifier, here
`#filename`. The generated test program can access the data using the
-identifier (without the #). The mechanism used is generic to Pandoc,
-and can be used to affect the typesetting by adding more attributes.
-For example, Pandoc can typeset the data in the code block using
-syntax highlighting, if the language is specified: `.markdown`,
-`.yaml`, or `.python`, for example.
+identifier (without the #).
Subplot also understands the `dot` and `roadmap` tags, and can use the
Graphviz dot program, or the [roadmap][] Rust crate, to produce
@@ -621,31 +600,23 @@ given file not-numbered-lines.txt
## Document metadata
-Pandoc supports, and Subplot makes use of, a [YAML metadata block][] in a
-Markdown document. This can and should be used to set the document
-title, authors, date (version), and can be used to control some of the
-typesetting. Crucially for Subplot, the bindings and functions files
-are named in the metadata block, rather than Subplot deriving them
-from the input file name.
-
-[YAML metadata block]: https://pandoc.org/MANUAL.html#extension-yaml_metadata_block
+Document metadata is read from a YAML file. This can used to set the
+document title, authors, date (version), and more. Crucially for
+Subplot, the bindings and functions files are named in the metadata
+block, rather than Subplot deriving them from the input file name.
-As an example, the metadata block for the Subplot document might look
-as follows. The `---` before and `...` after the block are mandatory:
-they are how Pandoc recongizes the block.
-
-~~~{.yaml .numberLines}
----
+~~~{.file .yaml .numberLines}
title: "Subplot"
authors:
- The Subplot project
date: work in progress
+markdowns:
+- subplot.md
bindings:
- subplot.yaml
impls:
python:
- subplot.py
-...
~~~
There can be more than one bindings or functions file: use a YAML
@@ -716,6 +687,24 @@ implementation functions:
* A binding for a "then everything is OK" step, which captures nothing,
and calls the `check_everything_is_ok` function.
+## Step functions and cleanup
+
+A step function must be atomic: either it completes successfully, or
+it cleans up any changes it made before returning an indication of
+failure.
+
+A cleanup function is only called for successfully executed step
+functions.
+
+For example, consider a step that creates and starts a virtual
+machine. The step function creates the VM, then starts it, and if both
+actions succeeds, the step succeeds. A cleanup function for that step
+will stop and delete the VM. The cleanup is only called if the step
+succeeded. If the step function manages to create the VM, but not
+start it, it's the step function's responsibility to delete the VM,
+before it signals failure. The cleanup function won't be called in
+that case.
+
### Simple patterns
The simple patterns are of the form `{name}` and match a single word
@@ -772,7 +761,7 @@ will emit a warning if the file is not found, and subplot codegen will emit an e
Bindings can contain an `impl` map which connects the binding with zero or more
language templates. If a binding has no `impl` entries then it can still be
-used to `docgen` a PDF or HTML document from a subplot document. This permits a
+used to `docgen` a HTML document from a subplot document. This permits a
workflow where requirements owners / architects design the validations for a
project and then engineers implement the step functions to permit the
validations to work.
@@ -802,8 +791,6 @@ given file badfilename.md
and file b.yaml
and file f.py
and an installed subplot
-when I run subplot docgen --merciful badfilename.subplot -o foo.pdf
-then file foo.pdf exists
when I try to run subplot codegen --run badfilename.md -o test.py
then command fails
```
@@ -825,6 +812,74 @@ given file missing.md
~~~
+### Bindings file strictness - given when then
+
+The bindings file is semi-strict. For example you must have only one
+of `given`, `when`, or `then` in your binding.
+
+
+```scenario
+given file badbindingsgwt.subplot
+and file badbindingsgwt.md
+and file badbindingsgwt.yaml
+and an installed subplot
+when I try to run subplot docgen --output ignored.html badbindingsgwt.subplot
+then command fails
+and stderr contains "binding has more than one keyword"
+```
+
+~~~{#badbindingsgwt.subplot .file .yaml .numberLines}
+title: Bad bindings cause everything to fail
+markdowns: [badbindingsgwt.md]
+bindings: [badbindingsgwt.yaml]
+~~~
+
+~~~{#badbindingsgwt.md .file .markdown .numberLines}
+# Bad bindings
+```scenario
+given we won't reach here
+```
+~~~
+
+~~~{#badbindingsgwt.yaml .file .yaml .numberLines}
+- given: we won't reach here
+ then: we won't reach here
+~~~
+
+### Bindings file strictness - unknown field
+
+The bindings file is semi-strict. For example, you must not have keys
+in the bindings file which are not known to Subplot.
+
+
+```scenario
+given file badbindingsuf.subplot
+and file badbindingsuf.md
+and file badbindingsuf.yaml
+and an installed subplot
+when I try to run subplot docgen --output ignored.html badbindingsuf.subplot
+then command fails
+and stderr contains "unknown field `function`"
+```
+
+~~~{#badbindingsuf.subplot .file .yaml .numberLines}
+title: Bad bindings cause everything to fail
+markdowns: [badbindingsuf.md]
+bindings: [badbindingsuf.yaml]
+~~~
+
+~~~{#badbindingsuf.md .file .markdown .numberLines}
+# Bad bindings
+```scenario
+given we won't reach here
+```
+~~~
+
+~~~{#badbindingsuf.yaml .file .yaml .numberLines}
+- given: we won't reach here
+ function: old_school_function
+~~~
+
## Functions file
Functions implementing steps are supported in Bash and Python. The
@@ -1074,7 +1129,7 @@ def foobar_was_done(ctx):
### Smoke test
The scenario below uses the input files defined above to run some tests
-to verify that Subplot can build a PDF and an HTML document, and
+to verify that Subplot can build an HTML document, and
execute a simple scenario successfully. The test is based on
generating the test program from an input file, running the test
program, and examining the output.
@@ -1085,8 +1140,6 @@ given file simple.md
and file b.yaml
and file f.py
and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
when I run subplot docgen simple.subplot -o simple.html
then file simple.html exists
when I run subplot codegen --run simple.subplot -o test.py
@@ -1097,6 +1150,92 @@ and step "then bar was done" was run
and command is successful
~~~
+## Indented scenario steps are not allowed
+
+_Requirement: A scenario step starts at the beginning of the line._
+
+Justification: We may want to allow continuing a step to the next
+line, but as of June, 2023, we haven't settled on a syntax for this.
+However, whatever syntax we do eventually choose, it will be easier
+to add that if scenario steps start at the beginning of a line,
+without making a breaking change.
+
+~~~scenario
+given file indented-step.subplot
+given file indented-step.md
+given file b.yaml
+given an installed subplot
+when I try to run subplot docgen indented-step.subplot -o foo.html
+then command fails
+and stderr contains "indented"
+~~~
+
+~~~{#indented-step.subplot .file .yaml .numberLines}
+title: Indented scenario step
+markdowns:
+ - indented-step.md
+bindings:
+ - b.yaml
+~~~
+
+~~~~~~{#indented-step.md .file .markdown .numberLines}
+# This is a title
+
+~~~scenario
+ given precondition
+~~~
+~~~~~~
+
+## Named code blocks must have an appropriate class
+
+_Requirement: Named code blocks must carry an appropriate class such as file or example_
+
+Justification: Eventually we may want to add other meanings to named blocks,
+currently the identifier cannot be used except to refer to the block as a named file,
+but we may want to in the future so this is here to try and prevent any future
+incompatibilities.
+
+~~~scenario
+given file named-code-blocks-appropriate.subplot
+given file named-code-blocks-appropriate.md
+given file b.yaml
+given an installed subplot
+when I try to run subplot docgen named-code-blocks-appropriate.subplot -o foo.html
+then command fails
+and stderr contains "#example-1 at named-code-blocks-appropriate.md:7:1"
+and stderr doesn't contain "example-2"
+and stderr doesn't contain "example-3"
+~~~
+
+~~~{#named-code-blocks-appropriate.subplot .file .yaml .numberLines}
+title: Named code blocks carry appropriate classes step
+markdowns:
+ - named-code-blocks-appropriate.md
+bindings:
+ - b.yaml
+~~~
+
+~~~~~~{#named-code-blocks-appropriate.md .file .markdown .numberLines}
+# This is a title
+
+~~~scenario
+given precondition
+~~~
+
+~~~{#example-1 .numberLines}
+This example is bad
+~~~
+
+~~~{#example-2 .file .numberLines}
+This example is OK because of .file
+~~~
+
+~~~{#example-3 .example .numberLines}
+This example is OK because of .example
+~~~
+
+~~~~~~
+
## No scenarios means codegen fails
If you attempt to `subplot codegen` on a document which contains no scenarios, the
@@ -1174,8 +1313,6 @@ given file allkeywords.md
and file b.yaml
and file f.py
and an installed subplot
-when I run subplot docgen allkeywords.subplot -o foo.pdf
-then file foo.pdf exists
when I run subplot codegen --run allkeywords.subplot -o test.py
then scenario "All keywords" was run
and step "given precondition foo" was run
@@ -1207,6 +1344,7 @@ but foobar was done
```
~~~
+<!-- disabled until Lars fixes typesetting of scenarios
### Keyword aliases in output
We support **and** and **but** in input lines, and we always render
@@ -1248,6 +1386,7 @@ then bar was done
then foobar was done
```
~~~
+-->
### Misuse of continuation keywords
@@ -1262,8 +1401,6 @@ given file continuationmisuse.md
and file b.yaml
and file f.py
and an installed subplot
-when I run subplot docgen continuationmisuse.subplot -o foo.pdf
-then file foo.pdf exists
when I try to run subplot codegen --run continuationmisuse.subplot -o test.py
then command fails
~~~
@@ -1300,8 +1437,8 @@ section. This scenario verifies that all markup works.
given file title-markup.subplot
given file title-markup.md
given an installed subplot
-when I run subplot docgen title-markup.subplot -o foo.pdf
-then file foo.pdf exists
+when I run subplot docgen title-markup.subplot -o foo.html
+then file foo.html exists
~~~
~~~~{#title-markup.subplot .file .yaml .numberLines}
@@ -1315,6 +1452,82 @@ impls: { python: [] }
# Introduction
~~~~
+## Scenario titles
+
+A scenario gets its title from the lowest level of section heading
+that applies to it. The heading can use markup.
+
+~~~scenario
+given file scenario-titles.subplot
+given file scenario-titles.md
+given file b.yaml
+given file f.py
+given an installed subplot
+when I run subplot metadata scenario-titles.subplot
+then stdout contains "My fun scenario title"
+~~~
+
+~~~~{#scenario-titles.subplot .file .yaml .numberLines}
+title: Test scenario
+markdowns:
+- scenario-titles.md
+bindings: [b.yaml]
+impls:
+ python: [f.py]
+~~~~
+
+~~~~{#scenario-titles.md .file .markdown .numberLines}
+# My **fun** _scenario_ `title`
+
+```scenario
+given precondition foo
+when I do bar
+then bar was done
+```
+~~~~
+
+## Duplicate scenario titles
+
+_Requirement: Subplot treats it as an error if two scenarios have the
+same title._
+
+Justification: the title is how a scenario is identified, and the user
+needs to be able to do so unambiguously.
+
+~~~scenario
+given file duplicate-scenario-titles.subplot
+given file duplicate-scenario-titles.md
+given file b.yaml
+given file f.py
+given an installed subplot
+when I try to run subplot metadata duplicate-scenario-titles.subplot
+then command fails
+then stderr contains "duplicate"
+~~~
+
+~~~~{#duplicate-scenario-titles.subplot .file .yaml .numberLines}
+title: Test scenario
+markdowns:
+- duplicate-scenario-titles.md
+bindings: [b.yaml]
+impls:
+ python: [f.py]
+~~~~
+
+~~~~{#duplicate-scenario-titles.md .file .markdown .numberLines}
+# My sceanrio
+
+```scenario
+when I do bar
+```
+
+# My sceanrio
+
+```scenario
+when I do bar
+```
+~~~~
+
## Empty lines in scenarios
This scenario verifies that empty lines in scenarios are OK.
@@ -1325,8 +1538,6 @@ given file emptylines.md
and file b.yaml
and file f.py
and an installed subplot
-when I run subplot docgen emptylines.subplot -o emptylines.pdf
-then file emptylines.pdf exists
when I run subplot docgen emptylines.subplot -o emptylines.html
then file emptylines.html exists
when I run subplot codegen --run emptylines.subplot -o test.py
@@ -1942,98 +2153,6 @@ def is_set_to(ctx, name=None, value=None):
-## Avoid changing typesetting output file needlessly
-
-### Avoid typesetting if output is newer than source files
-
-This scenario make sure that if docgen generates the bitwise identical
-output to the existing output file, it doesn't actually write it to
-the output file, including its timestamp. This avoids triggering
-programs that monitor the output file for changes.
-
-~~~scenario
-given file simple.subplot
-given file simple.md
-and file b.yaml
-and file f.py
-and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
-when I remember metadata for file simple.pdf
-and I wait until 1 second has passed
-and I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf has same metadata as before
-and only files simple.subplot, simple.md, b.yaml, f.py, simple.pdf exist
-~~~
-
-### Do typeset if output is older than subplot
-
-~~~scenario
-given file simple.subplot
-given file simple.md
-and file b.yaml
-and file f.py
-and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
-when I remember metadata for file simple.pdf
-and I wait until 1 second has passed
-and I touch file simple.subplot
-and I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf has changed from before
-~~~
-
-### Do typeset if output is older than markdown
-
-~~~scenario
-given file simple.subplot
-given file simple.md
-and file b.yaml
-and file f.py
-and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
-when I remember metadata for file simple.pdf
-and I wait until 1 second has passed
-and I touch file simple.md
-and I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf has changed from before
-~~~
-
-### Do typeset if output is older than functions
-
-~~~scenario
-given file simple.subplot
-given file simple.md
-and file b.yaml
-and file f.py
-and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
-when I remember metadata for file simple.pdf
-and I wait until 1 second has passed
-and I touch file f.py
-and I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf has changed from before
-~~~
-
-### Do typeset if output is older than bindings
-
-~~~scenario
-given file simple.subplot
-given file simple.md
-and file b.yaml
-and file f.py
-and an installed subplot
-when I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf exists
-when I remember metadata for file simple.pdf
-and I wait until 1 second has passed
-and I touch file b.yaml
-and I run subplot docgen simple.subplot -o simple.pdf
-then file simple.pdf has changed from before
-~~~
-
## Document structure
Subplot uses chapters and sections to keep together scenario snippets
@@ -2192,9 +2311,7 @@ given precondition foo
The document and code generators require a document title, because
it's a common user error to not have one, and Subplot should help make
-good documents. The Pandoc filter, however, mustn't require a document
-title, because it's used for things like formatting websites using
-ikiwiki, and ikiwiki has a different way of specifying page titles.
+good documents.
#### Document generator gives an error if input document lacks title
@@ -2277,6 +2394,7 @@ This is a very simple Markdown file that uses every kind of inline
markup in the title and chapter heading.
To satisfy codegen, we *MUST* have a scenario here
+
~~~~scenario
when I do bar
then bar was done
@@ -2513,32 +2631,6 @@ and file mtime.html contains "Geoffrey Butler"
and file mtime.html contains "2020-02-26 07:53"
~~~
-### Pandoc metadata
-
-~~~scenario
-given file pandoc.subplot
-given file pandoc.md
-and an installed subplot
-when I run subplot docgen pandoc.subplot -o pandoc.html
-when I run cat pandoc.html
-then file pandoc.html exists
-and file pandoc.html contains "<title>The Fabulous Title</title>"
-and file pandoc.html contains "Superlative Subtitle"
-~~~
-
-~~~{#pandoc.subplot .file .yaml .numberLines}
-title: The Fabulous Title
-markdowns:
-- pandoc.md
-pandoc:
- subtitle: Superlative Subtitle
-~~~
-
-~~~{#pandoc.md .file .markdown .numberLines}
-# Introduction
-This is a test document. That's all.
-~~~
-
### Missing bindings file
If a bindings file is missing, the error message should name the
@@ -2620,8 +2712,6 @@ and file b.yaml
and file other.yaml
and file f.py
and file other.py
-and file foo.bib
-and file bar.bib
and file expected.json
and an installed subplot
when I run subplot metadata images.subplot
@@ -2630,8 +2720,6 @@ and stdout contains "source: b.yaml"
and stdout contains "source: other.yaml"
and stdout contains "source: f.py"
and stdout contains "source: other.py"
-and stdout contains "source: foo.bib"
-and stdout contains "source: bar.bib"
and stdout contains "source: image.gif"
and stdout contains "bindings: b.yaml"
and stdout contains "bindings: other.yaml"
@@ -2652,7 +2740,6 @@ impls:
python:
- f.py
- other.py
-bibliography: [foo.bib, bar.bib]
~~~
~~~{#images.md .file .markdown .numberLines}
@@ -2666,34 +2753,12 @@ bibliography: [foo.bib, bar.bib]
~~~{#other.py .file .python .numberLines}
~~~
-~~~{#foo.bib .file .numberLines}
-@book{foo2020,
- author = "James Random",
- title = "The Foo book",
- publisher = "The Internet",
- year = 2020,
- address = "World Wide Web",
-}
-~~~
-
-~~~{#bar.bib .file .numberLines}
-@book{foo2020,
- author = "James Random",
- title = "The Bar book",
- publisher = "The Internet",
- year = 2020,
- address = "World Wide Web",
-}
-~~~
-
~~~{#expected.json .file .json}
{
"title": "Document refers to external images",
"sources": [
"b.yaml",
- "bar.bib",
"f.py",
- "foo.bib",
"image.gif",
"images.md",
"images.subplot",
@@ -2710,27 +2775,60 @@ bibliography: [foo.bib, bar.bib]
"other.py"
]
},
- "bibliographies": [
- "bar.bib",
- "foo.bib"
- ],
"files": [],
"scenarios": []
}
~~~
+### Multiple markdown files
+
+This scenario tests that the `markdowns` field in metadata can specify
+more than one markdown file.
+
+~~~scenario
+given file multimd.subplot
+given file md1.md
+given file md2.md
+given an installed subplot
+when I run subplot docgen multimd.subplot -o multimd.html
+when I run cat multimd.html
+then file multimd.html exists
+and file multimd.html contains "<title>The Fabulous Title</title>"
+and file multimd.html contains "First markdown file."
+and file multimd.html contains "Second markdown file."
+~~~
+
+~~~{#multimd.subplot .file .yaml .numberLines}
+title: The Fabulous Title
+authors:
+- Alfred Pennyworth
+- Geoffrey Butler
+date: WIP
+markdowns:
+- md1.md
+- md2.md
+~~~
+
+~~~{#md1.md .file .markdown .numberLines}
+First markdown file.
+~~~
+
+~~~{#md2.md .file .markdown .numberLines}
+Second markdown file.
+~~~
+
+
## Embedded files
Subplot allows data files to be embedded in the input document. This
is handy for small test files and the like.
-Handling of a newline character on the last line is tricky. Pandoc
-doesn't include a newline on the last line. Sometimes one is
-needed&mdash;but sometimes it's not wanted. A newline can be added by
-having an empty line at the end, but that is subtle and easy to miss.
-Subplot helps the situation by allowing a `add-newline=` class to be added
-to the code blocks, with one of three allowed cases:
+Handling of a newline character on the last line is tricky. The block
+ends in a newline on the last line. Sometimes one is needed&mdash;but
+sometimes it's not wanted. Subplot helps the situation by allowing a
+`add-newline=` class to be added to the code blocks, with one of three
+allowed cases:
* no `add-newline` class&mdash;default handling: same as `add-newline=auto`
* `add-newline=auto`&mdash;add a newline, if one isn't there
@@ -3187,7 +3285,7 @@ into SVGs such as this one.
~~~pikchr
arrow right 200% "Markdown" "Source"
box rad 10px "Subplot" "Document Generator" "(subplot docgen)" fit
-arrow right 200% "HTML+SVG/PDF" "Output"
+arrow right 200% "HTML+SVG" "Output"
arrow <-> down 70% from last box.s
box same "Pikchr" "Formatter" "(docs.rs/pikchr)" fit
~~~
@@ -3203,7 +3301,7 @@ when I run subplot docgen pikchr.subplot -o pikchr.html
then file pikchr.html matches regex /src="data:image/svg\+xml;base64,/
~~~
-The sample input file **pikchr.md**:
+The sample input file **pikchr.md:**
~~~~~~~~{#pikchr.md .file .markdown .numberLines}
---
@@ -3250,7 +3348,7 @@ when I run subplot docgen dot.subplot -o dot.html
then file dot.html matches regex /src="data:image/svg\+xml;base64,/
~~~
-The sample input file **dot.md**:
+The sample input file **dot.md:**
~~~~~~~~{#dot.md .file .markdown .numberLines}
This is an example Markdown file, which embeds a diagram using dot markup.
@@ -3299,7 +3397,7 @@ when I run subplot docgen plantuml.subplot -o plantuml.html
then file plantuml.html matches regex /src="data:image/svg\+xml;base64,/
~~~
-The sample input file **plantuml.md**:
+The sample input file **plantuml.md:**
~~~~~~~~{#plantuml.md .file .markdown .numberLines}
This is an example Markdown file, which embeds a diagram using
@@ -3387,7 +3485,7 @@ when I run subplot docgen roadmap.subplot -o roadmap.html
then file roadmap.html matches regex /src="data:image/svg\+xml;base64,/
~~~
-The sample input file **roadmap.md**:
+The sample input file **roadmap.md:**
~~~~~~~~{#roadmap.md .file .markdown .numberLines}
This is an example Markdown file, which embeds a roadmap.
@@ -3447,7 +3545,7 @@ markdowns:
When Subplot loads a document it will validate that the block classes
match a known set. Subplot has a built-in set which it treats as special,
-and it knows some pandoc-specific classes and a number of file type classes.
+and it knows some custom classes and a number of file type classes.
If the author of a document wishes to use additional class names then they can
include a `classes` list in the document metadata which subplot will treat
@@ -3522,3 +3620,192 @@ This is a test file.
~~~{#expected.txt .file}
This is a test file.
~~~
+## Mistakes in markdown
+
+When there are mistakes in the markdown input, Subplot should report
+the location (filename, line, column) where the mistake is, and what
+the mistake is. The scenarios in this section verify that.
+
+### Scenario before the first heading
+
+_Requirement: A scenario must follow a heading._
+
+Justification: the heading can be used as the title for the scenario.
+
+~~~scenario
+given an installed subplot
+given file scenario-before-heading.subplot
+given file scenario-before-heading.md
+when I try to run subplot docgen scenario-before-heading.subplot -o /dev/null
+then command fails
+then stderr contains "ERROR: scenario-before-heading.md:1:1: first scenario is before first heading"
+~~~
+
+~~~{#scenario-before-heading.subplot .file .yaml}
+title: Foo
+markdowns:
+ - scenario-before-heading.md
+~~~
+
+~~~~~~{#scenario-before-heading.md .file .markdown}
+~~~scenario
+~~~
+~~~~~~
+
+### Attempt to use definition list
+
+_Requirement: Attempt to use definition lists is reported._
+
+Justification: the markdown parser we use in Subplot doesn't support
+them, and it would be unhelpful to not tell the user if they try to
+use them.
+
+~~~scenario
+given an installed subplot
+given file dl.subplot
+given file dl.md
+when I try to run subplot docgen dl.subplot -o /dev/null
+then command fails
+then stderr contains "ERROR: dl.md:3:1: attempt to use definition lists in Markdown"
+~~~
+
+~~~{#dl.subplot .file .yaml}
+title: Foo
+markdowns:
+ - dl.md
+~~~
+
+~~~~~~{#dl.md .file .markdown}
+# Foo
+
+Some term
+: Definition of term.
+~~~~~~
+
+### Bad "add-newline" value
+
+_Requirement: Only specific values for the "add-newline" attribute are
+allowed for an embedded file._
+
+~~~scenario
+given an installed subplot
+given file add-newline.subplot
+given file add-newline.md
+when I try to run subplot docgen add-newline.subplot -o /dev/null
+then command fails
+then stderr contains "ERROR: add-newline.md:1:1: value of add-newline attribute is not understood: xyzzy"
+~~~
+
+~~~{#add-newline.subplot .file .yaml}
+title: Foo
+markdowns:
+ - add-newline.md
+~~~
+
+~~~~~~{#add-newline.md .file .markdown}
+~~~{#foo.txt .file add-newline=xyzzy}
+~~~
+~~~~~~
+
+## HTML output
+
+### Embedded CSS
+
+_Requirement:_ The user can specify CSS files to embed in the HTML
+output.
+
+Justification: We want to allow production of self-standing output
+with user-defined styling.
+
+~~~scenario
+given file embedded-css.subplot
+given file embedded-css.md
+given file embedded-css.css
+given file b.yaml
+given an installed subplot
+when I run subplot docgen embedded-css.subplot -o foo.html
+then file foo.html contains "silly: property;"
+~~~
+
+~~~{#embedded-css.subplot .file .yaml .numberLines}
+title: Embedded CSS
+markdowns:
+ - embedded-css.md
+bindings:
+ - b.yaml
+css_embed:
+ - embedded-css.css
+~~~
+
+~~~~~~{#embedded-css.md .file .markdown .numberLines}
+# This is a title
+
+~~~scenario
+given precondition
+~~~
+~~~~~~
+
+~~~{#embedded-css.css .file .css .numberLines}
+html {
+ silly: property;
+}
+~~~
+
+### CSS URLs
+
+_Requirement:_ The user can specify CSS URLs to add in the HTML
+output.
+
+Justification: We want to allow users to specify non-embedded CSS.
+
+~~~scenario
+given file css-urls.subplot
+given file css-urls.md
+given file b.yaml
+given an installed subplot
+when I run subplot docgen css-urls.subplot -o foo.html
+then file foo.html contains "https://example.com/flushing.css"
+~~~
+
+~~~{#css-urls.subplot .file .yaml .numberLines}
+title: Embedded CSS
+markdowns:
+ - css-urls.md
+bindings:
+ - b.yaml
+css_urls:
+ - https://example.com/flushing.css
+~~~
+
+~~~~~~{#css-urls.md .file .markdown .numberLines}
+# This is a title
+
+~~~scenario
+given precondition
+~~~
+~~~~~~
+
+
+## Running Subplot
+
+The scenarios in this section verify that the Subplot tool can be run
+in various specific ways.
+
+### Files not in current working directory
+
+_Requirement: Subplot can process a subplot that is not in the current
+working directory._
+
+~~~scenario
+given file x/simple.subplot from simple.subplot
+given file x/simple.md from simple.md
+given file x/b.yaml from b.yaml
+given file x/f.py from f.py
+given an installed subplot
+when I run subplot metadata x/simple.subplot
+then command is successful
+when I run subplot codegen x/simple.subplot -o test.py
+then file test.py exists
+when I run subplot docgen x/simple.subplot -o simple.html
+then file simple.html exists
+~~~