VirtualDub source code - Lina
Lina is the HTML compiler for VirtualDub's help system.
Syntax and input
The basic input format to Lina is almost XML, but not quite:
-
All elements are either paired (<p>...</p>), or are self-closed
(<p/>). There are no "provisionally open" tags, as in HTML 4 Transitional.
Lina enforces this and thus makes it impossible to forget a closing tag.
-
Correct tag pairing is enforced -- you cannot mix up end tags.
-
The starting document must have only one root tag.
-
XML violations: A schema/DTD is not required or used if present. Entities are not parsed. Attributes need not
be quoted and attribute minimization (no value) is allowed.
Lina constructs a parse tree from her input and uses that tree to write output. Attributes are quoted as necessary,
standalone tags are written without the self-close for greatest compatibility, and redundant whitespace is removed.
As a result, it is difficult to make common HTML structural errors.
Parsing phase
All control tags are of the form <lina:xxxx>. Two of these tags are special and execute as
soon as they are parsed:
- <lina:include src=file/> begins parsing of a separate file at the current tree point.
This inclusion is done on a file basis, so it is possible to begin a tag in one file and end it in another.
When the included file has been processed, parsing resumes in the original file.
- <lina:macro name=name> creates a macro with the given name, containing the given
contents. The macro is callable via the same <lina:xxxx> syntax.
These immediate tags are never placed in the tree; all other control tags are put in the tree and execute only
after the entire tree has been parsed.
Lina requires that non-space character data only appear within tags that allow them, and will error if it is present
elsewhere, such as immediately inside an <html> tag. The list of tags allowing CDATA can be augmented
using <lina:set-option>.
Execution phase
After parsing is complete, Lina then executes the parse tree from top to bottom:
- Text is output.
- Regular tags output themselves and their children.
- Macro and command tags fire when encountered.
In the process of doing so, three separate stacks are maintained:
- Execution stack: Holds all tags currently being executed.
- Context stack: Holds tags that establish reference points for data references -- macro calls, tag iterations. Relative
paths use the top-of-stack as the starting point.
- Construction stack: Holds tags and files that are currently being created.
When tags are being constructed, plain text and tags copy themselves into the new tag. If a file is being written,
the tags are output to that file. Otherwise, the output is discarded.
Control tags
- <lina:apply name="macro">...</lina:apply>
- Apply the named macro with each of the enclosed children as the given context.
- <lina:arg name="argname"/>
- Output the named attribute argument from the current macro context.
- <lina:attrib name="att-name">...</lina:attrib>
- Create an attribute in the currently constructing tag with the given contents.
- <lina:cdata>...</lina:cdata>
- Insert the enclosed text and tags with whitespace collapsing enabled.
- <lina:data>...</lina:data>
- Prohibit execution of enclosed tags. This tag is skipped during path searches.
- <lina:delay>...</lina:delay>
- Copy tags verbatim without execution into the output.
- <lina:dump-stack/>
- Dump current stacks to standard output for debugging.
- <lina:fireball src="src-file" dst="dst-file">
- Copy a file.
- <lina:for-each name="path">...</lina:for-each>
- Execute the tag body as a macro, with all tags referenced by the given path as the contexts.
- <lina:if-arg name="arg-name">...</lina:if-arg>
- Executes the tag body only if the current macro context has the named attribute argument.
- <lina:if-not-arg name="tag-name">.../<lina:if-not-arg>
- Executes the tag body only if the current macro context does not have the named attribute argument.
- <lina:if-not-present name="tag-name">...</lina:if-not-present>
- Executes the tag body only if the current macro context does not have the named tag.
- <lina:if-present name="tag-name">...</lina:if-present>
- Executes the tag body only if the current macro context has the named tag.
- <lina:pre>...</lina:pre>
- Insert the enclosed text and tags without whitespace collapsing enabled.
- <lina:pull name="path"/>
- Execute the contents of the tag specified by the given path in the current context.
- <lina:replace from="pattern" to="result">...</lina:replace>
- Execute the tag contents, replace all instances of pattern with result in the output, and
place the output into a new string tag.
- <lina:set-option name="link-truncate" baseurl="base-url" [notruncate]>
- Toggles extension truncation for links with the given prefix.
- <lina:set-option name="output-dir" target="path">
- Sets the output directory for file writes and file copies.
- <lina:set-option name="tag-info" tag="tag-name" cdata="y"|"n">
- Allows or disallows inline character data (CDATA) for the given tags.
- <lina:source>...</lina:source>
- Output the source to the enclosed tag structure as text in HTML.
- <lina:tag name="tag-name">...</lina:tag>
- Create a tag with the given name and body as contents, and then execute the created tag.
- <lina:write file="filename">...</lina:write>
- Execute the given body and write the output to a file.