1
0
Fork 0

Initial architecture documentation in manual

master
Mike Gerwitz 2017-03-28 13:29:31 -04:00
commit a9711fe139
10 changed files with 974 additions and 8 deletions

2
.gitignore vendored
View File

@ -7,7 +7,7 @@ Makefile.in
# generated by configure
src/version.js
config.*
/config.*
Makefile
package.json

View File

@ -12,7 +12,7 @@ build:
stage: build
script:
- autoreconf -fvi
- ./configure
- ./configure --with-srcuri="$SRCURI"
- npm install
- make all check info pdf html
artifacts:

View File

@ -41,6 +41,27 @@ AS_IF([node --harmony_destructuring >/dev/null 2>/dev/null],
AC_SUBST([NODE_DESTRUCTURE], [--harmony_destructuring])],
[AC_MSG_RESULT(no)])
set_devnotes='@set DEVNOTES'
AC_ARG_ENABLE(
[devnotes],
[AS_HELP_STRING([--enable-devnotes],
[include note for liza developers (enabled by default)])],
[test "x$enableval" != xno || set_devnotes="@c $set_devnotes"])
AC_SUBST([SET_DEVNOTES], [$set_devnotes])
set_srcuri='@c @set SRCURI <source code uri>'
AC_ARG_WITH(
[srcuri],
[AS_HELP_STRING([--with-srcuri],
[root URI for Liza source code cross-references
(disabled by default)])],
[test "x$withval" = x || set_srcuri="@set SRCURI $withval"])
AC_SUBST([SET_SRCURI], [$set_srcuri])
# generate files from their *.in counterparts
AC_CONFIG_FILES([Makefile doc/Makefile package.json src/version.js])
AC_CONFIG_FILES([Makefile package.json
doc/Makefile doc/config.texi
src/version.js])
AC_OUTPUT

1
doc/.gitignore vendored
View File

@ -19,3 +19,4 @@ Makefile
Makefile.in
stamp-vti
version.texi
config.texi

View File

@ -18,4 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##
MAKEINFOHTML = $(MAKEINFO) --html --css-include liza.css
info_TEXINFOS = liza.texi
liza_TEXINFOS = design.texi macros.texi config.texi liza.css

View File

@ -0,0 +1,7 @@
@c Manual configuration
@c whether to include notes for Liza developers
@SET_DEVNOTES@
@c URI to root of source tree for manual cross-references
@SET_SRCURI@

554
doc/design.texi 100644
View File

@ -0,0 +1,554 @@
@c This document is part of the Liza Data Collection Framework manual.
@c Copyright (C) 2017 LoVullo Associates, Inc.
@c
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.3
@c or any later version published by the Free Software Foundation;
@c with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
@c Texts. A copy of the license is included in the section entitled ``GNU
@c Free Documentation License''.
@node Design
@chapter Design & Architecture
@notice{
N.B. This document may reference features that are not yet
present in Liza; they will be moved into this repository in time.}
Liza is fundamentally a data collection framework@mdash{
}a fancy form for collecting, validating, and lightly processing
user data.
The main components of the system are:
@table @strong
@cindex Assertions
@item Assertions
Basic validations against bucket data,
producing errors and manipulating control flow.
Invokes triggers to manipulate the UI and document.
Assertions are compiled from Program sources.
@xref{Assertions}.
@cindex Bucket
@item Bucket
The key/value store into which all document data are stored.
Supports staging and rollback of data,
processing deltas,
and provides hooks that drive the rest of the system.
@xref{Bucket}.
@cindex Calculated Value
@item Calculated Values
A small sub-system for calculating bucket values from other values.
@cindex Client
@item Client
Basic logic for navigating between steps,
prompting for user actions,
display help text and basic document data,
communicate with server,
etc.
@xref{Client}.
@cindex Developer Dialog
@item Developer Dialog
Renders information about the system for debugging the client.
Can monitor the bucket, assertions, classification results, and
provides other useful features.
@cindex Predicate
@item Predicate System
Processes classification data from external classifiers to determine
applicability of specific questions.
These data are used to determine what assertions are performed,
what questions and groups display,
and more.
@xref{Predicate System}.
@cindex Program
@item Program
Internal representation of the Program with delegation of events to
the assertion system.
Contains compiled representation of all steps, groups, questions,
assertions, metadata, and others.
@xref{Program}.
@cindex Program, User Interface
@cindex User Interface, Program
@item Program UI
Rendering of elements specific to Programs,
such as steps, groups, and questions.
This is the equivalent of an HTML form.
Directly monitors the bucket to perform UI updates.
@xref{Program UI}.
@cindex Program, XML
@item Program XML
The source code for a Program, in XML format.
@xref{Program XML}.
@cindex Server
@item Server
Provides REST API for serving Programs; saving data;
revalidating, filtering, and recalculating data;
and other types of processing.
Code is shared with the client,
ensuring identical behavior for appropriate behaviors.
@cindex Type Validation
@cindex Validation, Type
@item Type Validation
Validates and formats bucket values for specific field (question)
types.
For example, a date field must be in a recognized date format,
and will be normalized for display.
@xref{Validation}.
@end table
More information about each can be found in their respective section.
@menu
* Assertions::
* Bucket::
* Client::
* Predicate System::
* Program::
* Program UI::
* Program XML::
* Validation::
@end menu
@node Assertions
@section Assertions
@maintstart
@footnote{
Assertions are compiled from the Program XML (@pxref{Program XML}).
Rather than using a library,
it compiles a mess of largely duplicate code inline.
This system needs to be @emph{replaced},
not modified.
A replacement can either be in the form of a library (removing most
if not all code generation from the Program XML compiler),
or possibly compile into classifications and use the classification
system.
@emph{The latter option is preferred,
and would be more powerful with less maintenance.}}
@maintend
@helpwanted
@node Bucket
@section Bucket
@helpwanted
@menu
* Value Assignment:Bucket Assignment. Writing data to the Bucket.
@end menu
@c TODO
@node Bucket Assignment
@subsection Bucket Value Assignment
@helpwanted
@node Client
@section Client
@maintstart
@footnote{
The client is largely managed by a single class,
@srcref{src/client/Client.js, Client},
which has grown out of control.
@code{Client} mediates essentially the entire system.
Code is to be extracted out of this class as it is touched.
The other system mammoth is @code{Ui} (@pxref{Program UI}).}
@maintend
@helpwanted
@menu
* Error Handling::
@end menu
@node Error Handling
@subsection Error Handling
@maintenance{
The complexity of this system and integration into legacy
layers has caused maintenance trouble in the past.
Each of the error checking layers need to be integrated
to reduce complexity.}
@cindex Error
@cindex Failure
There are three layers of error checking:@footnote{
Primarily for legacy reasons.
They are being consolodated as the system is touched.}
@enumerate
@item Required field checking@mdash{
}whether all required questions have been answered.
@item Type Validation@mdash{
}verify that questions contain valid data according to their
declared type. @ref{Validation}.
@item Assertions@mdash{
}arbitrary checks on data.
@ref{Assertions}.
@end enumerate
@cindex Required Field
@cindex Field, Required
@cindex Field, Fixed
@cindex Error, Fixed
@cindex Error, Required
@cindex Fixed, Error
Required fields fail serially@mdash{
}the system will notify the user of the required field,
and direct him/her to it (usually through scrolling).
A field is marked as @dfn{fixed} according to the rules
in @ref{Managing Error State}.
@menu
* Managing Error State:: Determining when failures should be marked as ``fixed''
@end menu
@node Managing Error State
@subsubsection Managing Error State
@cindex Failure Stack
@cindex Error Stack
Each failure caused by assertions is associated with a
@dfn{failure stack}.
The stack represents the trail of assertions that have run,
containing the ids of all values asserted against.
When any field or classification changes that is represented on the
failure stack,
the failure for the failed field associated with that failure stack
is cleared.
@exnotice{
If an assertion for some question @var{foo} first checked the value
of bucket field @var{bar},
and within its failure checked the value @var{c:predicate},
the failure stack would contain both of those ids.
If either @var{bar} or the @var{predicate} classification changed,
the question @var{foo} would have its error cleared.}
Error state is managed by
@srcref{src/validate/ValidStateMonitor.js, ValidStateMonitor}.
@node Predicate System
@section Predicate System
@maintstart
@footnote{
New programs (using the old incarnation of TAME) use the classifier
embedded into the rater by TAME.
Old ones, however, still use the @dfn{Global Classifier}.
This system isn't as well tested as TAME's@mdash{
}which needs to work properly for the sake of calculating premium@mdash{
}and has suffered from a number of bugs in the past.
The solution is to migrate all programs to TAME and remove that old
code.}
@maintend
@tip{
For a practical application of these concepts, see its use in the
Program@tie{}XML (@pxref{Specifying Predicates}).}
@cindex Predicate
@cindex Classifier
@cindex Applicability
@cindex Domain of discourse, Predicate
The @dfn{predicate system} determines the @dfn{applicability} of
certain objects (like questions and assertions) by associating them
with predicates.
The domain of discourse (variables which may be quantified) is listed
in @ref{t:predicate-dod}.
What it means for some object to be applicable depends on the context.
@float Table, t:predicate-dod
@multitable @columnfractions 0.25 0.10 0.65
@headitem Type @tab Prefix @tab Description
@item Classifications
@tab @emph{None}
@tab Results of applying an external @dfn{classifier} to the bucket
(@pxref{Bucket}).
@item Bucket Truth Predicate
@tab @code{q:}
@tab
Whether the given name in the bucket (@pxref{Bucket}) is
non-empty and non-zero.
The prefix @samp{q:} refers to its most common use
case---questions (@pxref{Program UI,,Program@tie{}UI}).
@end multitable
@caption{Predicate system domain of discourse}
@end float
This system is limited to universal quantification over the domain of
discourse.
For other quantifiers and higher-order logic,
defer to one of the systems that contributes to the domain of
discourse,
like the classifier.@footnote{
This is usually TAME.
The Program XML also supports inline classifications
with TAME's syntax (@pxref{Specifying Predicates}).}
Predicates are usually specified in the Program XML
(@pxref{Specifying Predicates}) and compiled into the program
(@pxref{Program}).
@node Program
@section Program
@maintstart
@footnote{
The @code{Program} class was one of the first prototypes created,
and has evolved poorly with the rest of the system.
It is the base class for all compiled programs,
and it glues together too many other systems with a terrible
API and little to no encapsulation.
With that said, it is one of the least touched classes (thus its
state); developers rarely have the need to touch @code{Program}.}
@maintend
@mvnotice{
The core @code{Program} class that causes maintenance concerns needs
to be added to Liza.
It is currently mocked as necessary in test cases.}
@cindex Program
The @dfn{Program} is a declarative representation of an entire system.
It is the highest level of abstraction from a data perspective.
The user observes and interacts with a Program using the
@ref{Program UI,,Program@tie{}UI}.
@cindex Program, XML
Programs contain a lot of metadata that is not in a convenience
human-readable (or modifiable) format,
some of which are redundant.
Programs are ideally compiled from a @ref{Program XML,,Program@tie{}XML}
document.
@node Program UI
@section Program UI
@maintenance{
The @code{Ui} class,
in addition to @srcref{src/client/Client,Client} (@pxref{Client}),
represent the two monoliths of the system.
This mediates all UI-related tasks,
and still has far too many concerns with far too many
dependencies.
Code is to be extracted out of this class as it is touched.
}
@mvnotice{
All @file{program/ui/} contents still need to be moved into Liza.}
@cindex Program, User Interface
@cindex User Interface, Program
The @dfn{Program UI} renders a @ref{Program} as a form.
@cindex Step
@cindex Group
At the highest level,
steps are rendered in a tab-like manner,
above the main form content.
A step contains groups,
which in turn contain elements such as questions.
Groups are delimited in some manner defined by their style
(@pxref{Group Styles}).
@cindex Question
@cindex Question, Value Formatting
@cindex Bucket, Updating
Questions are rendered as form fields.
Any time the respective @ref{Bucket} field is changed,
the form field is updated to reflect those changes,
after having first been formatted with the appropriate validator
(@pxref{Formatting Values}).
When a question is changed by the user,
the value is expected to be propagated to the Bucket
(@pxref{Bucket Assignment}).
@cindex Navigation Bar
@cindex User Interface, Navigation Bar
@cindex User Interface, Button Navigation
Navigation between steps can be done via the
@dfn{Navigation Bar} above the step@tie{}content,
or using ``Go@tie{}Back'' and ``Continue'' buttons at the foot of the
step@tie{}content.
@cindex Sidebar
A @dfn{Sidebar} is rendered adjacent to the step content.
It displays the name of the Program,
as well as configurable metadata (usually through the @samp{sidebar}
node of the @ref{Program XML,,Program@tie{}XML}).
It also displays question help text (also configured through the XML)
and any error messages (@pxref{Error Handling}).
@menu
* Group Styles:: Different ways of displaying groups of questions to
the user.
@end menu
@node Group Styles
@subsection Group Styles
@refactor{
Some group styles still use jQuery;
they should be modified to use modern formatters and Liza DOM
abstractions (see @srcrefraw{src/ui/field}
and @srcrefraw{src/ui/styler}).}
@cindex Group, Styling
Groups support a number of @dfn{group styles} that determine how
they are delimited from other groups;
how the elements they contain are rendered and laid out;
and how multiple indexes are displayed, added, and removed.
A list of available styles is detailed in @ref{t:group-styles}.
@float Table, t:group-styles
@multitable @columnfractions 0.15 0.65 0.10 0.10
@headitem Name @tab Description @tab Multi-Index? @tab Add/Remove Index?
@item @samp{default}
@tab
Groups are unstyled by default@mdash{
}they render elements as flat fields like a traditional form.
Only the first index of elements is rendered.
@tab@center N
@tab@center N
@item @samp{collapsetable}
@tab
Renders element label in the leftmost column like @samp{sidetable}.
Indexes are groups of rows delimited by headings,
which collapse the respective group of rows when clicked.
@tab@center Y
@tab@center Add
@item @samp{sidetable}
@tab
Renders elements as rows with label in the leftmost column rather
than the top row.
Each index is rendered as a column.
@tab@center Y
@tab@center Add
@item @samp{tabbedblock}
@tab
Each group is rendered as a block,
with each index rendered as a tab to the right of it.
Clicking a tab toggles the body content to the associated index.
Elements are rendered within the box.
@tab@center Y
@tab@center N
@item @samp{tabbed}
@tab
Like @samp{default},
but each index has a tab at the top of the group.
Clicking a tab toggles the body content to the associated index.
@tab@center Y
@tab@center Y
@item @samp{table}
@tab
A vanilla table with elements as columns,
their labels across the top row.
Each index is rendered in its own row.
@tab@center Y
@tab@center Y
@end multitable
@caption{Group styles and index support}
@end float
@node Program XML
@section Program XML
@helpwanted
@menu
* Specifying Predicates::
@end menu
@node Specifying Predicates
@subsection Specifying Predicates
Object predicates (@pxref{Predicate System}) are specified using the
@xmlattr{when} attribute of certain nodes.
It must contain a string of references understood by the system
(see domain of discourse, @ref{Predicate System}),
all of which much match for the predicate to be true.
@float Figure, f:pred-when
@example
<question id="describe" type="noyes"
label="Any special notes for this location?" />
<question id="vacant_desc" type="textarea"
when="q:describe vacant property"
label="Show only when a vacant property with the
question 'describe' non-empty and non-zero" />
@end example
@caption{Using the @xmlattr{when} attribute}
@end float
In @ref{f:pred-when} above,
question @samp{vacant_desc} will be applicable when @emph{all} of
the values of @samp{vacant}, @samp{property},
and@tie{}@samp{q:describe} are true.@footnote{
@xref{Predicate System} for what ``true'' means for a particular
variable in the domain of discourse.}
Within the context of the @progxml,
this concretely means that the classifications
@samp{vacant} and@tie{}@samp{property} are true,
and that the question @samp{describe} is answered ``yes''.
It reads as a sentence:
``@samp{vacant_desc}'' is applicable when we should @tie{}``describe
a vacant property''.
@node Validation
@section Validation
@helpwanted
@menu
* Formatting Values::
@end menu
@node Formatting Values
@subsection Formatting Values
@cindex Question
@cindex Question, Value Formatting
@helpwanted

156
doc/liza.css 100644
View File

@ -0,0 +1,156 @@
/*
Copyright (C) 2016-2017 Oliver Heimlich
Copyright (C) 2017 LoVullo Associates, Inc.
This file is part of Octave.
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>.
*/
/** modified by LoVullo Associates **/
/** TODO: loading fonts from Google is a privacy issue; download as part
of build and self-host **/
@import url('https://fonts.googleapis.com/css?family=Noto+Sans');
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono');
/* Use custom fonts */
code, kbd, samp, tt, pre { font-family: 'Roboto Mono', monospace; }
code, kbd, samp, tt { font-style: italic; padding: 0 0.1ex; /* slightly increase margin to surrounding text */ }
body, .sansserif { font-family: 'Noto Sans', sans-serif; }
h1, h2, h3, h4, h5, .menu-comment, .roman, .menu-preformatted { font-family: 'Noto Sans', serif; }
/*
Use colors from the solarized color theme (sparsely),
the main text will remain in default colors for optimal readability (black on white).
*/
pre.example, .header, .float-caption, hr
{
/* base00 ~ body text in light solarized theme */
color: #657b83;
border-color: #657b83;
}
pre.example
{
/* base3 ~ background color in light solarized theme */
background-color: #fdf6e3;
padding: 0.5em;
font-size: 0.9em;
}
a { color: #268bd2; /* blue */ }
a:visited { color: #d33682; /* magenta */ }
/** added by LoVullo Associates **/
.float
{
margin-block-start: 2em;
margin-block-end: 2em;
}
/* Center floating tables and images */
.float table, .float img, .float object { margin-left: auto; margin-right: auto; }
/* Decrease table width, but not on small screens */
.float table { max-width: 38em; }
/* Use horizontal lines: above/below tables and after table headers (Chicago Style) */
.float table, .float th { border-collapse: collapse; border-top: 1px solid black; border-bottom: 1px solid black; }
.float th, .float td { padding: 0.5em; }
/* Use horizontal ruler with double lines */
hr { border-width: 0; border-top-width: 3px; border-style: double; }
/* Smaller gap between subsequent @group blocks */
.example { margin-bottom: 1em; }
.example + .example { margin-top: -0.5em }
/* Smaller gap between definition and its description */
dd > p:first-child { margin-top: 0.5em; }
/* Limit maximum body width such that text is easier to read */
body { max-width: 42em; margin-left: 0.5em; margin-right: 0.5em; }
/* On small screens don't indent the code examples to prevent overflow */
div.example { margin-left: auto; max-width: 38.8em; }
/*
Use left margin such that text is easier to read,
but don't sacrifice space on small screens.
*/
@media screen and (min-width: 43em)
{
/* Smooth transition for screens between 43em and 57em */
body { margin-left: auto; margin-right: auto; }
@media (min-width: 57em)
{
body { margin-left: 7.5em; }
}
}
/** added by LoVullo Associates **/
.doc-notice
{
border-left: 5px solid #657b83;
margin: 0px;
padding-block-start: 0.25em;
padding-block-end: 0.25em;
}
.doc-notice p
{
padding-left: 1em;
margin: 0px;
}
.doc-notice.dev
{
border-color: #d33682;
}
.doc-notice.dev p::before,
.doc-notice.tip p::before
{
display: block;
float: left;
margin-left: -1.5em;
}
.doc-notice.dev p::before
{
color: #d33682;
content: '\01F6A7';
}
.doc-notice.tip p::before
{
content: '\261E';
}
.doc-notice.dev p,
.doc-notice.tip p
{
padding-left: 1.75em;
}
.footnote-notice.dev p:first-child::before
{
content: '\01F6A7';
margin-right: 0.5em;
}
/* "Example:" */
.doc-notice.ex strong:first-child
{
color: #657b83;
}

View File

@ -1,6 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c This document is part of the Liza Data Collection Framework manual.
@c Copyright (C) 2014 LoVullo Associates, Inc.
@c
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.3
@c or any later version published by the Free Software Foundation;
@ -9,17 +10,24 @@
@c Free Documentation License''.
@c %**start of header
@include config.texi
@include version.texi
@include macros.texi
@c Developer Notes index (used only if DEVNOTES)
@defindex dn
@setfilename liza.info
@settitle Liza Data Collection Framework v@value{VERSION}
@c %**end of header
@include version.texi
@documentencoding UTF-8
@c %**end of header
@copying
This manual is for the Liza Data Collection Framework, version
@value{VERSION}.
Copyright @copyright{} 2014 LoVullo Associates, Inc.
Copyright @copyright{} 2014, 2017 LoVullo Associates, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@ -44,6 +52,21 @@ Free Documentation License''.
@insertcopying
@end titlepage
@devnotice{
This manual contains inline notes for developers of Liza.@footnote{
To disable for user documentation, pass @option{--disable-devnotes}
to @command{configure}.}
For an index of notes@comma{} see @ref{Developer Notes Index}.}
@ifclear SRCURI
@devnotice{
Location of Liza source code is unknown.
Source cross-references have been disabled.@footnote{
To enable source code cross-references, provide the URI to the
root (as you want it to be seen in the manual) via
@option{--with-srcuri=<uri>} to @command{configure}.}}
@end ifclear
@contents
@ifnottex
@ -51,13 +74,30 @@ Free Documentation License''.
@top Main
@end ifnottex
@c This is where @menu will go
@menu
* Design and Architecture:Design. Design and structure of framework
* Concept Index::
@ifset DEVNOTES
* Developer Notes Index:: Index of pertenant notes for developers of Liza.
@end ifset
@end menu
@ifnottex
@insertcopying
@end ifnottex
@c This is where the includes will go.
@include design.texi
@node Concept Index
@unnumbered Concept Index
@printindex cp
@ifset DEVNOTES
@node Developer Notes Index
@unnumbered Developer Notes Index
@printindex dn
@end ifset
@bye

184
doc/macros.texi 100644
View File

@ -0,0 +1,184 @@
@c This document is part of the Liza Data Collection Framework manual.
@c Copyright (C) 2017 LoVullo Associates, Inc.
@c
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.3
@c or any later version published by the Free Software Foundation;
@c with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
@c Texts. A copy of the license is included in the section entitled ``GNU
@c Free Documentation License''.
@c unicode CONSTRUCTION SIGN
@macro constructionsign
🚧
@end macro
@c insert appropriate em dash for mode
@ifnottex
@macro mdash
@inlinefmtifelse{html, @inlineraw{html,&mdash;}, —}
@end macro
@end ifnottex
@c the macro for TeX for some reason always seems to be followed
@c by a space when applied; #1 consumes it and re-adds if it's
@c not empty
@tex
\gdef\mdash#1{%
---%
\def\next{#1}%
\ifx\next\empty\relax\else#1\fi%
}
@end tex
@c inline documentation notice for some sort of quality
@c improvement or warning
@macro noticestart{type}
@html
<div class="doc-notice \type\">
@end html
@end macro
@macro noticeend{}
@html
</div>
@end html
@end macro
@c vanilla notice
@macro notice{text}
@noticestart{}
@emph{\text\}
@noticeend
@end macro
@c notice for developers of liza
@macro devnotice{text}
@ifset DEVNOTES
@noticestart{dev}
@emph{\text\}
@noticeend
@end ifset
@end macro
@c indicate that help is needed to produce docs
@macro helpwanted{}
@cindex TODO, Missing Docs
@dnindex Missing Docs
@notice{There's nothing here yet. Maybe you can help?}
@end macro
@c maintenance note for developers
@c
@c N.B. use @maintstart and @maintend manually if using multiple
@c paragraphs otherwise PDF output (TeX) breaks; we'll figure out
@c a better solution in the future
@macro maintstart{}
@dnindex Maintenance Concern
@noticestart{dev}
This system has maintenance concerns.
@end macro
@macro maintend
@noticeend
@end macro
@macro maintenance{desc}
@maintstart
@footnote{\desc\}
@maintend
@end macro
@c encapsulated to avoid bad TeX generation (fails compilation
@c when inlined at call site)
@macro maintfoot{desc}
@html
<div class="footnote-notice dev">
@end html
\desc\
@emph{Developers should evaluate whether extra time should be
allocated for tasks involving this system.}
@html
</div>
@end html
@end macro
@c non-critical maintenance notes
@macro refactor{desc}
@dnindex Refactor
@devnotice{Portions of this system need refactoring.@footnote{
\desc\}}
@end macro
@c simple textual example
@macro exnotice{text}
@noticestart{ex}
@strong{Example:} \text\
@noticeend
@end macro
@c needs to be moved into liza
@macro mvnotice{text}
@noticestart{mv}
@emph{All or part of this system needs to be moved into Liza.}@footnote{
\text\}
@noticeend
@end macro
@macro tip{text}
@noticestart{tip}
\text\
@noticeend
@end macro
@c link to source file if URI is known, otherwise display
@c the path to the file
@ifset SRCURI
@macro srcref{path, display}
@url{@value{SRCURI}/\path\, @code{\display\}}
@end macro
@macro srcrefraw{path}
@url{@value{SRCURI}/\path\, @code{\path\}}
@end macro
@end ifset
@ifclear SRCURI
@macro srcref{path, display}
@srcrefraw{\path\}
@end macro
@macro srcrefraw{path}
@file{\path\}
@end macro
@end ifclear
@c XML formatting
@macro xmlnode{name}
@samp{\name\}
@end macro
@macro xmlattr{name}
@samp{@@\name\}
@end macro
@c text to avoid repeated e.g. ties and other formatting
@macro progxml
Program@tie{}XML
@end macro