Not up for a full syntax lesson? Download and print this three-page quick start guide. It has pretty flowcharts.
QnA is a markup language for people with little or no programming experience. It was designed with attorneys in mind and transforms blocks of text into interactive question and answer sessions (QnAs). These QnAs can be used as stand-alone expert systems or in the aid of rule-based document construction. See example below. Plus, they can be fun, and the entire project is open source.
Authors define behavior by placing text after one of ten tags described below. On this page, you'll find everything you need to write your own QnA. Assuming an average reading speed of 180 words per minute, this entire page should only take about 20 minutes to read. Of course, you should probably open a QnA editor and play around as you read. So it might take an hour before you're an expert. ;)
If you're pressed for time, start with the Body Tags section. That's where all the exciting stuff happens, and you can build a very respectable QnA with body tags alone. Alternatively, you could try our quick start guide.
The header is optional text appearing before the first non-header tag (those tags listed under Body below). The header can be empty or contain any of the following five header tags. The values of these tags are defined by the text between tags. The order of tags is unimportant as long as they appear before the first non-header tag. If you use a tag twice, the last value provided will be used to define the tag's value.
Title: text/html
Title
tag are visible in the credits at the bottom of the QnA output and as the title of any stand-alone HTML page. The contents of this tag are also used to define the title element in Open Graph metadata associated with any stand-alone HTML page. Contents may include HTML, but such styling will only appear in the credits, not in the HTML page's title or metadata.
Author: text/html
Author
tag are visible in the credits at the bottom of the QnA output. Contents may include HTML.
Description: text/html
Description
tag are visible in the credits at the bottom of the QnA output. They are also used to define the description element in Open Graph metadata associated with any stand-alone HTML page. Contents may include HTML, but such styling will only appear in the credits, not in the HTML page's metadata.
Before: text/html
After: text/html
The Body is where you define questions and answers along with the text of any would-be documents. This content can be plain text, or it can be formated as HTML. The output of a QnA is an interactive HTML document. Consequently, if you would like to include comments (text that doesn't show up in your output), you can hide them like this: <!-- comment text here -->
, just as you would in HTML. To get a good feel for what's possible in QnA, read through the following tag descriptions.
Q(variable_name): text/html
Q
(question) tags are rendered inside left-aligned text bubbles. The first Q
tag's content is visible after loading. The content of other Q
tags become visible after a user selects its preceding A
tag.
For example, the first question below is displayed after loading, along with its possible answers (those A
tags in a vertical line below its Q
). After a user selects an answer, the content of the Q
following that answer is displayed, along with its possible answers (if any).
Q: first question A: first answer to first question Q: first question under the first answer to the first question A: second answer to first question Q: first question under the second answer to the first question | |
edit this QnA in an new window |
The Q
tag must start a new line or be indented exactly once more than the preceding A
tag.
After rendering, by an interpreter every Q
tag will have a unique variable_name
placed in a parenthetical between its Q and colon based on its relation to other Q
tags. If left in the default form of alternating numbers and periods (e.g., 1.1.1.3.4), these variable_name
s are updated with every rendering. You can, however, change these default names to any unique combination of letters, numbers, periods, dashes, and underscores (e.g., my_cool_vaiable). Regardless of the format, variable_name
s can be used in conjunction with the GOTO
tag to direct users to Q
tags that would otherwise be inaccessible given the linear nesting of questions and answers. A discussion of the GOTO
tag can be found below.
Q(1): A: Q(1.1): A: Q(1.2): Q(2):
Formatting:
QnA outputs HTML files. So you can format questions in their text bubbles using standard HTML. If, however, you would like the text of a question to display in multiple text bubbles, use <br><br>
to create a bubble break. This will split the current text bubble in two at the point where it is included. You may recognize this as two HTML line breaks. If you want to place two HTML line breaks in a bubble without triggering a bubble break, simply add a space between the two tags (<br> <br>
), and they will not create a bubble break.
GOTO:variable_name
The GOTO
tag moves a user to the location targeted by its variable_name
.
For example, given the QnA below, a user answering "Red Sox" will find themselves presented with the reply "Cool." Whereas, a user answering "Yankees" will find him/herself presented with the text "Seriously..." followed by the original question, "Red Sox or Yankees?"
Q(1): Red Sox or Yankees? A: Red Sox Q(1.1):GOTO:2 A: Yankees Q(1.2): Seriously... GOTO:1 Q(2): Cool. | |
edit this QnA in an new window |
GOTO
calls can only appear at the end of a Q
tag, and there can only be one GOTO
call per tag. They are not allowed in A
tags.
If the target of a GOTO
is removed or the variable_name
shows up more than once before the ids are recalculated: the GOTO
is declared ambiguous; an error is thrown; and GOTO:variable_name
becomes something like GOTO:???
. If the target of a GOTO
is renumbered, in most cases, the GOTO
is renumbered as well.
Note: DOC:
tags (described below) are included when a user is moved to a target location.
A(variable_value): some text/html
,
A(variable_value)[href]: some text/html
, or
A(variable_value):[href] some text/html
The A
tag is rendered as a button following the preceding question's text. By default, clicking on this button will replace all buttons with a right-aligned word bubble containing the contents of the selected button and followed by the text of the next nested question in a left-aligned text bubble.
The A
tag must line up with the preceding Q
tag (i.e., have the same number of tabs between it and the start of the line). You can have as many A
tags following a Q
as you like. For example:
Q: A: A: A: Q: A: A:
Advanced Usage:
Answers are stored in variables with names defined by
variable_name
in the parent Q
tag. By default, answer values are equal to the text/html in the A
tag. However, if the A
tag is written with parentheses (e.g., A():
) the contents of these parentheses are used as the answer.
You can access an answer's values by enclosing its variable_name
like so: <x>variable_name</x>
. Instances of such enclosures will be replaced with that variable's value. For example, consider the following.
Q(drink): Coffee or tea? A: coffee Q(1.1):GOTO:extras A: tea Q(1.2):GOTO:extras Q(extras): Milk and sugar? A(milk and sugar): Yes. Milk and sugar. Q(2.1):GOTO:gotit A(nothing added): No. I take it black. Q(2.2):GOTO:gotit A(milk): Milk only. Q(2.3):GOTO:gotit A(sugar): Sugar only. Q(2.4):GOTO:gotit Q(gotit): Got it. You like <x>drink</x> with <x>extras</x>. | |
edit this QnA in an new window |
Note: the replacement of <x>variable_name</x>
with user values includes text inside DOC:
tags (described below).
In addition to the replacement example above, user answers are stored in the document itself. So if you use the submit2()
function (described below) these variables will be passed along. Also, you can get at these values using Javascript's innerHTML property: document.getElementById("variable_name").innerHTML.
If the A
tag is written with brackets (e.g., A[]:
or A:[]
) the contents of the brackets will be passed to that button's href attribute. That is, the button can be turned into a link. If the brackets fall before the colon, the link will target the page the button is on. If the brackets follow the colon, the href will target a new blank page/window. In HTML, A[http://www.nasa.gov]: I love NASA
effectively becomes <a href="http://www.nasa.gov">I love NASA</a>
, whereas, A:[http://www.nasa.gov] I love NASA
effectively becomes <a href="http://www.nasa.gov" target="_blank">I love NASA</a>
.
When used in conjunction with QnA's predefined Javascript functions (described below), the href argument can do some neat stuff above and beyond linking to things because you can uses a href to run Javascript.
For example, you could use the save2()
and transcript()
functions to let a user save their conversation to a file.
Q(1): Do you want to see something neat? A: Yes. Q(1.1): Cool. Click away. A[javascript:save2('transcript.txt', transcript());]: Save conversation. Q(1.1.1):GOTO:1 A: No. Q(1.2):GOTO:1 | |
edit this QnA in an new window |
X:date_type
,
X[href]:date_type
, or
X:[href]date_type
Use the X
tag in the place of an A
tag when you would like users to type their own answer. Instead of a button, it will present as a input/text field. The contents of such a field is saved as the question's variable value, and its names is based on the Q
tag's variable_name
. By default, a blank data_type
will result in a text field. Valid data types include: text
, number
, date
, datetime-local
, and time
. These are a subset of HTML5 input types. See HTML Input Types
As with the A
tag, if the X
tag is written with brackets (e.g., A[]:
or A:[]
) the contents of the brackets will be passed to something approximating an href. That is, the button can be turned into a link or used to run Javascript.
As stated above, if you enclose a variable name like so <x>variable_name</x>
it will be replaced by that variable's value, in this case the user input for the X
tag.
For example, in the QnA below, if a user types in "David," the QnA's reply would read "Nice to meet you David."
Q(name): What is your name? X: Q: Nice to meet you <x>name</x>. | |
edit this QnA in an new window |
Note: as with A
tags, the replacement of <x>variable_name</x>
with user values includes text inside DOC:
tags (described below).
Advanced Usage:
When the X
tag is used, as with the A
tag, in addition to the replacement described above, user answers are stored in the document itself. So if you use the submit2()
function (described below) user variables will be passed along. Also, you can get at these values using Javascript's innerHTML property: document.getElementById("variable_name").innerHTML.
DOC: text/html
You associate a DOC:
tag with a Q:
tag by placing it in line with and directly before the Q:
tag. When a Q
tag is displayed to a user, the content of its associated DOC:
tag is added to a QnA document variable.
For example, in the QnA below, items are added to a shopping list based on the meals a user selects. You are then presented with two options for viewing the shopping list: (1) on screen by reading the contents of the document into an standard Javascript alert window; or (2) saving the shopping list as a text file using the save2()
function (described below). Both methods access the document via the doc()
function (described below).
DOC(1):SHOPPING LIST Q(1): What would you like to cook? A: Garlic Chicken DOC(1.1):Garlic Chicken 4 boneless skinless chicken breasts 4 garlic cloves, minced 4 tablespoons brown sugar 1 tablespoon olive oil additional herbs and spices, as desired Q(1.1):GOTO:2 A: Mac and Cheese DOC(1.2):Mac and Cheese 3/4 pound dried elbow macaroni 1 1/2 cups grated sharp cheddar cheese 1/2 cup grated gruyere cheese 1/3 cup panko bread crumbs, toasted until golden Q(1.2):GOTO:2 Q(2): Okay. I have the shopping list ready. How would you like it? A[javascript:alert(doc());]: In an alert box. Q(2.1):GOTO:3 A[javascript:save2('list.txt',doc());]: As a file I can save. Q(2.2):GOTO:3 Q(3): Enjoy the grub. | |
edit this QnA in an new window |
Advanced Usage:
You can make use of the submit2()
function (described below) to pass your document to either an HTML or Markdown parser/editor. So instead of saving a document directly to ones computer, a user could have a chance to edit his/her document before saving.
Note: the DOC:
content is just text. It doesn't matter if it's HTML, markdown, LaTeX, CommonAccord, whatever you like.
All interactive QnA documents come preloaded with a set of eight Javascript functions. As described above, these can be called from an A
tag using the syntax: A[javascript:function_name();]:
. Below we'll explain what each of these functions do.
transcript(format);
This function will return a transcript of the current QnA as it exists at the time the function is called. For example, when selected, the following tag will display a transcript in an alert window. A[javascript:alert(transcript());]: button text
.
This function accepts an argument called format
. When set equal to 1
, the transcript will include HTML found in the original QnA questions and answers. Otherwise, all HTML will be removed from the presented transcript. For example, this call will include HTML A[javascript:alert(transcript('1'));]:
, and this one will not
A[javascript:alert(transcript());]:
.
You may recall the use of this function from the shopping list example above.
getvar(variable_name);
This function will return the vale of the defined variable_name
. For example, when selected, the following tag will display the value stored in the name
variable: A[javascript:alert(getvar('name'));]: button text
.
goto(variable_name);
This function will cause the QnA to jump to the Q
tag associated with the defined variable_name
. For example, when selected, the following tag will cause the QnA to jump to the Q(end)
tag: A[javascript:goto('end');]: button text
.
doc();
This function will return the DOC:
content associated with rendered Q
tags. For example, when selected, the following tag will display the DOC:
content: A[javascript:alert(doc());]: button text
.
You may recall the use of this function in the save conversation example above.
json_str();
This function will return a JSON string containg the QnA's variable_name
and variable_name
as key and value pairs. For example, when selected, the following tag will display the the QnA's variables as a JSON string: A[javascript:alert(json_str());]: button text
.
csv();
This function will return a string of comma-separated values containing the variable names in the first row and the values of variables collected by the QnA in the second row. For example, when selected, the following tag will display the the QnA's variables as comma-separated values: A[javascript:alert(csv());]: button text
.
mail2(to, subject, body);
When called, this function will make use of the mailto URI scheme to open a new email in the user's default email program. This email will be addressed to to
, with the subject line subject
, and the body of the email will be body
. For example, when selected, the following tag will email a transcript of the current QnA to jdoe@example.com with the subject line QnA Transcript. A[javascript:mail2('jdoe@example.com','QnA Transcript',transcript());]: button text
.
save2(filename,content);
filename
and content equal to content
. For example, when selected, the following tag will save a file named QnA_document.txt with contents equal to the output of the doc()
function. A[javascript:save2('QnA_document.txt',doc());]: button text
.
You may recall the use of this function from the save conversation example above.
submit2(action, method, docAs, instructions, transcriptAs, jsonAs, target);
action
, its method to method
, and its target to target
. Note: the target
parameter is optional. It's default setting is: target = "_self"
.
It will send the QnA's document as a single variable named docAs
along with an HTML transcript named transcriptAs
and a JSON string named jsonAs
.
It will send all variables defined with their names as defined by the Q
tag's variable_name
as well as any hidden variables placed inside the document's Before
, After
, Q
and A
tags.
Additionally, it will send a variable named i
with a value equal to instructions
. This last variable is intended specifically for use with the WYSIWYG document parsers described below.
My hope is that this section will grow into a list of parsers as people point me to various parsers around the web. The basic idea is that by using the submit2()
function in conjunction with a document parser/editor, it is possible to hold up the document created by a QnA for review by a person. Imagine a QnA that used a combination of DOC:
and X:
tags to craft a custom document for a pro se litigant. At the end of the QnA, that document can be passed to a parser and the user can take some time to edit the text before printing or saving it. The thing is that the DOC:
tag doesn't really care what format its content is in. It could be HTML, markdown, or LaTex. By passing that content to a parser, it can be rendered and placed in a form that's easier for a user to digest.
For now, I've set up local parsers for HTML, Markdown, and jsPDF. They are available at:
Note: the jsPDF parser doesn't allow users to edit output, and isn't compatible with all browsers.
The parsers read two variables which you can send them using the submit2()
function. The first, t
, is the content to be parsed, and the second, i
, is a set of instructions to be displayed after parsing. In fact, submit2()
takes i
as an argument. That is i
= instructions
as defined above.
For example, the QnA below can be used to create a letter to Santa. Note: the document is in HTML. So you'll notice that line breaks are indicated by the HTML tag <br>. Also, it is sent to the HTML parser.
Q(1): Would you like to write a letter to Santa? A: Yes. Q(myname): What is your name? X: DOC(1.1.1):Dear Santa,<br><br> Q(naughty): Have you been naughty or nice? A(I am sorry that I have been naughty. I will work hard to be nice in the new year.<br><br>): Naughty Q(1.1.1.1):GOTO:whatiwant A(): Nice Q(1.1.1.2):GOTO:whatiwant A: No. Q(1.2): That's cool. Have a good day. Q(whatiwant): What would you like for Christmas? X: DOC(2.1):<x>naughty</x>I would like <x>whatiwant</x> for Christmas. I hope all is well with you up north.<br><br> Sincerely,<br> <x>myname</x> Q(2.1): Alright, are you ready to see your letter? A[javascript:submit2('https://www.qnamarkup.net/doc/parse/html/', 'POST', 't', 'Proof read your letter. Print it out, and mail it to: Santa Clause, North Pole')]: Yes. Q(2.1.1): Thank you. |
edit this QnA in an new window |
Although the above parsers offer a good deal of flexability, sometime you want to control a document's format with greater percision than allowed by HTML et al. For such instances, you can make use of .docx templates such as this one.
Instead of constructing the document in QnA you can merge your QnA answers with an existing template. Below we'll do this with a standard .docx (Word) file with mail merge feilds. The service below will take in a JSON string, the URL of a .docx file from which to make a merged .docx file, and the name for the output file. The service we'll be using below is a modified instance of docx_webmerge. Here's a brief how to on how to create your own template file.
However, the tool only accepts .docx files from a whitelist of servers. if you're a non-profit and would like me to add your website to the whitelist, let me know. As long as you aren't expecting wicked crazy volume, I'll probably just add you to the list.
Your output can be either a .docx file or a .pdf file. To choose a filetype, simpily use the appropriate endpoint (e.g. https://colarusso.pythonanywhere.com/2docx/ or https://colarusso.pythonanywhere.com/2pdf/).
That being said, let us write another letter to Santa.
Before: <input type="hidden" name="name" value="Letter to Santa"/> <input type="hidden" name="docx_uri" value="http://www.qnamarkup.org/docxmerge/templates/Santa-letter.docx"/> Q(1): Would you like to write a letter to Santa? A: Yes. Q(myname): What is your name? X: Q(1.1.1):GOTO:whatiwant Q(whatiwant): What would you like for Christmas? X: Q(2.1):Alright, are you ready to see your letter? A[javascript:submit2('https://colarusso.pythonanywhere.com/2docx/', 'POST', '', '', '', 'json_doc', '_blank')]:Yes (docx). A[javascript:submit2('https://colarusso.pythonanywhere.com/2pdf/', 'POST', '', '', '', 'json_doc', '_blank')]:Yes (pdf). Q(2.1.1): Thank you. |
edit this QnA in an new window |
Note: if you'd like to include instructions along with your document, consider appending an instructions page to the begining of the document.
If you have a text file containing QnA Markup at a URL, you can pass that URL to a QnA instance for rendering using the source
parameter and the following syntax:
[QnA rendering instance's URL]/i/?source=[QnA text file's URL]
For example:
https://www.qnamarkup.net/i/?source=https://colarusso.github.io/QnAMarkup/examples/source/first_q.txt
(view link)Permissible domains, however, are limited to a whitelist established in the configuration file (i.e., config.php) of a QnA instance. The instance running at QnAMarkup.org, for example, accepts pointers to "www.qnamarkup.org" and "colarusso.github.io".
The source
parameter is accepted by both the the stand-alone QnA page (e.g., https://www.qnamarkup.net/i/?source=text URL
) and the editor page (e.g., https://www.qnamarkup.org/?source=text URL
).
You can submit content to "colarusso.github.io" by following the instructions for "Hosting your QnA" found on this project's Gallery page.
Back to top