Commit 7c811a6e authored by Kim Nguyễn's avatar Kim Nguyễn
Browse files

Add a copy of the website generating program (slightly modified to output

to stdout) to the non regression tests.
parent ab031336
Pipeline #146 passed with stages
in 6 minutes and 49 seconds
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<page name="memento">
<title>Quick reference</title>
<left>
<p>This page briefly presents the syntax of the CDuce language.</p>
<boxes-toc/>
<p>See also:</p>
<local-links href="index,manual,tutorial"/>
</left>
<box title="Identifiers" link="id">
<ul>
<li> Type and Pattern identifiers: words formed by of Unicode letters and
the underscore "_" character, starting by an uppercase letter. </li>
<li> value identifiers: words formed by of Unicode letters and the underscore "
_" character, starting by a lowercase letter or underscore.</li>
</ul>
</box>
<box title="Scalars" link="scalars">
<ul>
<li>Large integers:
<ul>
<li>Values: <code>0,1,2,3,...</code> </li>
<li>Types: intervals <code>-*--10, 20--30, 50--*, ...</code>,
singletons <code>0,1,2,3,...</code> </li>
<li>Operators: <code>+,-,/,*,div,mod, int_of</code> </li>
</ul>
</li>
<li>Floats:
<ul>
<li>Values: <i>none built-in</i>. </li>
<li>Types: only <code>Float</code>. </li>
<li>Operators: <code>float_of</code> : String -> Float</li>
</ul>
</li>
<li>Unicode characters:
<ul>
<li>Values: quoted characters (<code>'a'</code>, <code>'b'</code>,
<code>'c'</code>, ...,<code>'あ'</code>, <code>'い'</code>, ... ,
<code>'私'</code>, ... , <code>'⊆'</code>, ...),
codepoint-defined characters (<code>'\x%%h%%;' '\%%d%%;'
</code> where <code>%%h%%</code> and
<code>%%d%%</code> are hexadecimal and decimal integers
respectively), and backslash-escaped characters
(<code>'\t'</code> tab, <code>'\n'</code> newline,
<code>'\r'</code> return, <code>'\\'</code> backslash).</li>
<li>Types: intervals <code>'a'--'z', '0'--'9'</code>,
singletons <code>'a','b','c',...</code> </li>
<li>Operators: <code>char_of_int</code> : Int -> Char, <code>int_of_char</code> : Char -> Int</li>
</ul>
</li>
<li>Symbolic atoms:
<ul>
<li>Values: <code>`A, `B, `a, `b, `true, `false, ...</code> </li>
<li>Types: singletons <code>`A, `B, ...</code> </li>
<li>Operators: <code>make_atom</code> : (String,String) -> Atom,
<code>split_atom</code> : Atom -> (String,String) </li>
<li>CDuce also supports <local href="namespaces">XML Namespaces</local></li>
</ul>
</li>
</ul>
</box>
<box title="Operators, built-in functions" link="op">
<ul>
<li>Infix:
<br/> <code>@</code> : concatenation of sequences
<br/> <code>+,*,-,div,mod</code> : Integer,Integer -> Integer
<br/> <code>=, &lt;&lt;, &lt;=, &gt;&gt;, &gt;= </code> :
<i>t</i>,<i>t</i> -> Bool = <code>`true | `false</code> (any non functional type <i>t</i>)
<br/> <code>||, &amp;&amp;</code> : Bool,Bool -> Bool
<br/> <code>not</code>: Bool -> Bool
</li>
<li>Prefix:
<br/><code>load_xml</code> : Latin1 -> AnyXml,
<br/><code>load_html</code> : Latin1 -> [ Any* ],
<br/><code>load_file</code> : Latin1 -> Latin1,
<br/><code>load_file_utf8</code> : Latin1 -> String,
<br/><code>dump_to_file</code> : Latin1 -> String -> [],
<br/><code>dump_to_file_utf8</code> : Latin1 -> String -> [],
<br/><code>print_xml</code> : Any -> Latin1,
<br/><code>print_xml_utf8</code> : Any -> String,
<br/><code>print</code> : Latin1 -> [],
<br/><code>print_utf8</code> : String -> [],
<br/><code>dump_xml</code> : Any -> [],
<br/><code>dump_xml_utf8</code> : Any -> [],
<br/><code>int_of</code> : String -> Int,
<br/><code>float_of</code> : String -> Float,
<br/><code>string_of</code> : Any -> Latin1,
<br/><code>char_of_int</code> : Int -> Char,
<br/><code>make_atom</code> : (String,String) -> Atom,
<br/><code>split_atom</code> : Atom -> (String,String),
<br/><code>system</code> : Latin1 -> { stdout = Latin1; stderr = Latin1;
status = (`exited,Int) | (`stopped,Int) | (`signaled,Int)
},
<br/><code>exit</code> : 0--255 -> Empty,
<br/><code>getenv</code> : Latin1 -> Latin1,
<br/><code>argv</code> : [] -> [ String* ],
<br/><code>raise</code> : Any -> Empty
</li>
</ul>
</box>
<box title="Pairs" link="pair">
<ul>
<li>Expressions: <code>(e1,e2)</code> </li>
<li>Types and patterns: <code>(t1,t2)</code> </li>
<li>Note: tuples are right-associative pairs; e.g.:
<code>(1,2,3)=(1,(2,3))</code> </li>
<li>When a capture variable appears on both side of a pair pattern,
the two captured values are paired
together (e.g. <code>match (1,2,3) with (x,(_,x)) -> x ==>
(1,3)</code>). </li>
</ul>
</box>
<box title="Sequences" link="seq">
<ul>
<li>Expressions: <code>[ 1 2 3 ]</code>,
which is syntactic sugar for <code>(1,(2,(3,`nil)))</code> </li>
<li>A sub-sequence can be escaped by !: <code>[ 1 2 ![ 3 4 ] 5
]</code> is then equal to <code>[ 1 2 3 4 5 ]</code> . </li>
<li>Types and patterns : <code>[ R ]</code> where <code>R</code> is
a regular expression built on types and patterns:
<ul>
<li>A type or a pattern is a regexp by itself, matching a single
element of the sequence </li>
<li>Postfix repetition operators: <code>*,+,?</code>
and the ungreedy variants (for patterns) <code>*?, +?
,??</code></li>
<li>Concatenation of regexps</li>
<li>For patterns, sequence capture variable <code>x::R</code> </li>
</ul>
</li>
<li>It is possible to specify a tail, for expressions, types, and patterns;
e.g.: <code>[ x::Int*; q ]</code> </li>
<li>Map: <code>map e with p1 -> e1 | ... | pn -> en</code>.
Each element of e must be matched. </li>
<li>Transform: <code>transform e with p1 -> e1 | ... | pn -> en</code>.
Unmatched elements are discarded; each branch returns a sequence
and all the resulting sequences are concatenated together. </li>
<li>Selection: : <code>select %%e%% from %%p1%% in %%e1%% ... %%pn%%
in %%en%% where %%e'%%</code>. SQL-like selection with the possibility
of using CDuce patterns instead of variables. <code>%%e1%% ...
%%en%%</code> must be sequences and <code>%%e'%%</code> a boolean
expression.</li>
<li>Operators: concatenation <code>e1 @ e2 = [ !e1 !e2 ]</code>,
flattening <code>flatten e = transform e with x -> x</code>.
</li>
</ul>
</box>
<box title="Record" link="record">
<ul>
<li>Records literal <code>{ l1 = e1; ...; ln = en }</code></li>
<li>Types: <code>{ l1 = t1; ...; ln = tn }</code> (closed, no more
fields allowed), <code>{ l1 = t1; ...; ln = tn; .. }</code> (open,
any other field allowed). Optional fields: <code>li =? ti</code>
instead of <code>li = ti</code>. Semi-colons are optional.</li>
<li>Record concatenation: <code>e1 + e2</code>
(priority to the fields from the right argument) </li>
<li>Field removal: <code>e1 \ l</code> (does nothing if the
field <code>l</code> is not present)</li>
<li>Field access: <code>e1.l</code></li>
<li>Labels are in fact Qualified Names (see <local href="namespaces"/>)</li>
</ul>
</box>
<box title="Strings" link="string">
<ul>
<li>Strings are actually sequences of characters.</li>
<li>Expressions: <code>"abc", [ 'abc' ], [ 'a' 'b' 'c' ]</code>. </li>
<li>Operators: <code>string_of, print, dump_to_file</code></li>
<li><code>PCDATA</code> means <code>Char*</code> inside regular expressions</li>
</ul>
</box>
<box title="XML elements" link="xml">
<ul>
<li>Expressions: <code> &lt;(tag) (attr)>content</code> </li>
<li>If the tag is an atom <code>`X</code>, it can be written
<code>X</code> (without the <code>(..)</code>).
Similarly, parenthesis and curly braces may be omitted
when attr is a record <code>l1=e1;...;ln=en</code>
(semicolon can also be omitted in this case).
E.g: <code>&lt;a href="abc">[ 'abc' ]</code>.</li>
<li>Types and patterns: same notations.</li>
<li>XPath like projection: <code>%%e%%/%%t%%</code>. For every
XML tree in <code>%%e%%</code> it returns the sequence of children
of type <code>%%t%%</code></li>
<li>Tree transformation: <code>xtransform e with p1 -> e1 | ... | pn -> en</code>.
Applies to sequences of XML trees. Unmatched elements are left unchanged and the
transformation is recursively applied to the sequence of children of the unmatched
element; as for transform, each branch returns a sequence
and all the resulting sequences are concatenated together. </li>
<li>Operators: <code>load_xml : Latin1 -> AnyXml; print_xml : Any ->
Latin1; dump_xml : Any -> []</code>
</li>
</ul>
</box>
<box title="Functions" link="fun">
<ul>
<li>Expressions:
<ul>
<li>General form: <code>fun f (t1->s1;...;tn->sn)
p1 -> e1 | ... | pm -> em</code> (<code>f</code> is optional) </li>
<li>Simple function: <code>fun f (p : t) : s = e</code>,
equivalent to <code>fun f (t -> s) p -> e</code> </li>
<li>Multiple arguments: <code>fun f (p1 : t1, p2 : t2,...) : s =
e</code>, equivalent to <code>fun f ((p1,p2,...):(t1,t2,...)) : s
= e</code> (note the blank spaces around colons to avoid ambiguity
with namespaces) </li>
<li>Currified function: <code>fun f (p1 : t1) (p2 : t2) ... : s =
e</code> (can be combined with the multiple arguments syntax).</li>
</ul>
</li>
<li>Types: <code>t -> s</code> </li>
</ul>
</box>
<box title="Pattern matching, exceptions, ..." link="match">
<ul>
<li>Type restriction: <code>(e : t)</code> (forgets any more precise
type for <code>e</code>; note the blank spaces around colons to avoid ambiguity with namespaces) </li>
<li>Pattern matching: <code>match e with p1 -> e1 | ... | pn ->
en</code></li>
<li>Local binding: <code>let p = e1 in e2</code>, equivalent to
<code>match e1 with p -> e2</code>;
<code>let p : t = e1 in e2</code> equivalent to
<code>let p = (e1 : t) in e2</code> </li>
<li>If-then-else: <code>if e1 then e2 else e3</code>, equivalent to
<code>match e1 with `true -> e2 | `false -> e3</code></li>
<li>Exceptions: <ul>
<li>Raise exception: <code>raise e</code></li>
<li>Handle exception: <code>try e with p1 -> e1 | ... | pn ->
en</code></li>
</ul> </li>
</ul>
</box>
<box title="More about types and patterns" link="type">
<ul>
<li>Boolean connectives: <code>&amp;,|,\</code> (<code>|</code> is
first-match). </li>
<li>Empty and universal types: <code>Empty,Any</code> or
<code>_</code>.</li>
<li>Recursive types and patterns: <code>t where T1 = t2 and ... and
Tn = tn</code>.</li>
<li>Capture variable: <code>x</code>. </li>
<li>Default values: <code>(x := c)</code>. </li>
</ul>
</box>
<box title="References" link="ref">
<ul>
<li>Type: <code>ref %%T%%</code>.</li>
<li>Construction: <code>ref %%T%% %%e%%</code>.</li>
<li>Dereferencing: <code>!%%e1%%</code>.</li>
<li>Assignment: <code>%%e1%% := %%e2%%</code>.</li>
</ul>
</box>
<box title="Toplevel statements" link="toplevel">
<ul>
<li>Global expression to evaluate.</li>
<li>Global let-binding.</li>
<li>Global function declaration.</li>
<li>Type declarations: <code>type T = t</code>.</li>
<li>Global <local href="namespaces">namespace</local>:
<code>namespace p = "..."</code>,
<code>namespace "..."</code>.</li>
<li>Source inclusion: <code>include %%filename_string%%</code>.</li>
<li>Debug directives: <code>debug %%directive argument%%</code> <br/>
where <code>%%directive%%</code> is one of the following: <code>accept</code>,
<code>subtype</code>, <code>compile</code>, <code>sample</code>, <code>filter</code>. <br/>
Use <code>#help debug</code> for a short description.
</li>
<li>Toplevel directives: <code>#env</code>, <code>#quit</code>,
<code>#reinit_ns</code>.</li>
</ul>
</box>
</page>
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<site>
<title>CDuce</title>
<header>
<global_header>
<p>
</p>
</global_header>
</header>
<footer>
<meta>
<p>
<a href="mailto:webmaster@cduce.org">Webmaster</a> -
<local href="sitemap">Site map</local>
</p>
</meta>
</footer>
<include file="../../common/memento.xml"/>
</site>
(** Input types **)
type Site = <site>[ <title>String Header? Footer? H_script* Page ]
type Header = <header>[ <global_header>Content Item* ]
type Footer = <footer>[ Item* ]
type Page = <page name=Latin1 url=?String new=?""
vertbar=?("true"|"false")>[ <title>String <banner>[InlineText*]?
<page_header>Flow? <page_footer>Flow? Item*]
type External = <external href=String title=String name=String>[]
type Item =
<box ({title=String; link=String; short=?String} | {})>Content
| <halfwidth_box title=String link=String position=?("left"|"right") short=?String>Content
| <halfwidth_box position=?("left"|"right")>Content
| <meta>Content
| <left>Content
| <footnotes>[]
| Page
| External
type Author = <author presenter=?("yes"|"no")>String
type Paper =
<paper file=?String old=?"">[
<title>String Author+ <comment>[InlineText*] <abstract>Content ]
type Slides =
<slides file=String>[ <title>String Author+ <comment>[InlineText*] ]
type Link =
<link url=String title=String>[ InlineText* ]
type Content =
[ ( <p style=?String>[InlineText*]
| <ol style=?String>[<li>Content +]
| <section title=String>Content
| <sample highlight=?"true"|"false">String
| <xmlsample highlight=?"true"|"false">String
| <sessionsample highlight=?"true"|"false">String
| H_table
| Paper | Slides | Link
| <boxes-toc short=?"" sections=?"">[]
| <pages-toc sections=?"">[]
| <site-toc>[]
| <local-links href=String>[]
| <two-columns>[ <left>Content <right>Content ]
| <note title=?String> Content
| <footnotes>[]
| <xhtml>Flow
| <demo label=?String prefix=?String>String
| <ul>[<li>Content +]
| InlineText
)* ]
type InlineText =
Char
| <(`b|`i|`tt|`em) style=?String>[InlineText*]
| <code>String
| <local href=String>String
| <footnote nocount=?"true">[InlineText*]
| H_a | H_img | H_br |H_script
| <thumbnail href=String width=?IntStr height=?IntStr>[]
| <thumbnails href=String width=?IntStr height=?IntStr>[ PCDATA ]
type IntStr = ['0'--'9'+]
type Special = H_br | H_span | H_bdo | H_map | H_object | H_img;;
type Fontstyle = H_tt | H_i | H_b | H_big | H_small;;
type Phrase = H_em | H_strong | H_dfn | H_code | H_q |
H_samp | H_kbd | H_var | H_cite | H_abbr | H_acronym | H_sub
| H_sup;;
type InlineForms = H_input | H_select | H_textarea | H_label | H_button;;
type MiscInline = H_ins | H_del | H_script;;
type Misc = H_noscript | MiscInline;;
type Inline = H_a | Special | Fontstyle | Phrase | InlineForms;;
type Inlines = [ (Char | Inline | MiscInline)* ];;
type Heading = H_h1 | H_h2 | H_h3 | H_h4 | H_h5 | H_h6;;
type Lists = H_ul | H_ol | H_dl;;
type Blocktext = H_pre | H_hr | H_blockquote | H_address;;
type Block = H_p | Heading | H_div | Lists | Blocktext | H_fieldset | H_table;;
type Blocks = [ (Block | H_form | Misc)* ];;
type Flow = [ (Char | Block | H_form | Inline | Misc)* ];;
This diff is collapsed.
include "xhtml-strict.cd" (* XHTML 1 Strict DTD *)
include "xhtml-categ.cd" (* Categories (Inline, ...) from this DTD *)
......@@ -30,6 +30,14 @@
(rule (alias overloading) (action (diff overloading.exp overloading.out)))
; end: overloading.cd
; begin: web_site.cd
(rule (deps web_site.cd) (target web_site.cdo)
(action (ignore-outputs (with-accepted-exit-codes 0 (run cduce --compile %{deps})))))
(rule (deps web_site.cdo) (target web_site.out)
(action (ignore-stderr (with-stdout-to %{target} (with-accepted-exit-codes 0 (run cduce --run %{deps}))))))
(rule (alias web_site) (action (diff web_site.exp web_site.out)))
; end: web_site.cd
(alias (name runtest)
(deps
(source_tree ../../common)
......@@ -37,4 +45,5 @@
(alias integers)
(alias lazy)
(alias overloading)
(alias web_site)
))
(* This CDuce script produces CDuce web site. *)
(* The types *)
include "../../common/xhtml.cd";;
include "../../common/siteTypes.cd";;
(** Command line **)
let (input,outdir) = ("../../common/site.xml", "")
(** Generic purpose functions **)
(* Recursive inclusion of XML files and verbatim text files *)
let load_include (Latin1 -> [Any*])
name ->
(* let _ = print [ 'Loading ' !name '... \n' ] in *)
xtransform [ (load_xml name) ] with
| <include file=(s & Latin1)>[] -> load_include s
| <include-verbatim file=(s & Latin1)>[] -> load_file s
| <include-forest file=(s & Latin1)>[] ->
match load_xml ("string:<fake>"@(load_file s)@"</fake>") with
<fake> x -> x | _ -> raise "Uhh?"
(* Loading *)
let [<site>[ <title>site
(<header>header | /(header:=[]))
(<footer>footer | /(footer:=[]))
extra_head::H_script*
main_page ] ] =
(* match load_include input with
[ Site ] & x -> x
| _ -> exit 2 *)
try (load_include input :? [ Site ])
with err & Latin1 ->
print ['Invalid input document:\n' !err '\n'];
exit 2
(* Highlighting text between {{...}} *)
let highlight (String -> [ (Char | H_strong | H_i)* ] )
| [ '{{ON}}'; rest ] -> xhighlight rest
| [ '{{%%' h ::(Char *?) '%%}}' ; rest ] ->
[ <strong class="highlight">[<i>h]; highlight rest ]
| [ '{{' h ::(Char *?) '}}' ; rest ] ->
[ <strong class="highlight">h; highlight rest ]
| [ '$$%%' h ::(Char *?) '%%$$' ; rest ] ->
[ <strong class="ocaml">[<i>h]; highlight rest ]
| [ '$$' h ::(Char *?) '$$' ; rest ] ->
[ <strong class="ocaml">h; highlight rest ]
| [ '%%' h ::(Char *?) '%%' ; rest ] ->
[ <i>h; highlight rest ]
| [ c; rest ] -> [ c; highlight rest ]
| [] -> []
let xhighlight (String -> [ (Char | H_strong | H_i)* ] )
| [ x::('}}' | ':}' | '{{' | '{:') h::Char*?
y::('}}' | ':}' | '{:' | '{{'); rest ] ->
[ !x <strong class="highlight">h !y; xhighlight rest ]
| [ c; rest ] -> [ c; xhighlight rest ]
| [] -> []
(* Split a comma-separated string *)
let split_comma (String -> [String*])
| [ x::(Char*?) ',' ; rest ] -> (x, split_comma rest)
| s -> [ s ]
type wschar = ' ' | '\n' | '\t' | '\r'
let split_thumbnails (String -> [(String,String)*])
| [ wschar* x::(Char\wschar\':')+ ':' y::_*? '.'; rest ] ->
((x,y), split_thumbnails rest)
| [ wschar* x::(Char\wschar)+; rest ] ->
((x,""), split_thumbnails rest)
| [ wschar* ] -> []
(** Internal types **)
type Path = [ { url=String title=String }* ]
type Tree = { name=String url=String title=String
children=[Tree*] boxes=[H_ul?] }
let url_of_page (Page -> String)
| <page url=u ..>_ -> u
| <page name=n ..>_ -> n @ ".html"
let render(a : String)(p : {presenter=?"yes"|"no" ..}) : Flow =
match p with
| {presenter="yes" ..} -> [<strong class="ocaml">a]
| _ -> a
let authors ([Author+] -> Flow)
| [ <author (p)>a ] -> render a p
| [ <author (p1)>a1 <author (p2)>a2 ] ->
(render a1 p1) @ ", and " @ (render a2 p2)
| [ <author (p)>a; rem ] -> (render a p)@ ", " @ authors rem
let find_local_link (sitemap : [Tree*], l : String) : Tree =
match sitemap with
| (h,t) ->
if (h . name = l) then h
else
(try find_local_link (t,l) with `Not_found ->
find_local_link (h . children,l))
| [] -> raise `Not_found
let local_link (sitemap : Tree, l : String, txt : String) : [Inline?] =
try
let h = find_local_link ([sitemap],l) in
let txt = if txt = "" then h . title else txt in
[ <a href=(h . url)>txt ]
with `Not_found ->
dump_to_file "/dev/stderr" [ 'Warning. Local link not found: ' !(string_of l) '\n' ];
[]
let compute_sitemap ((Page|External) -> Tree)
| <page name=name ..>[ <title>title (c::(Page|External) | _)* ] & p ->
let children = map c with p -> compute_sitemap p in
{ name url=(url_of_page p) title children boxes=(boxes_of p) }
| <external name=name href=h title>[] ->
{ name url=h title children=[] boxes=[] }
let ul([H_li*] -> [H_ul?]) [] -> [] | l -> [ <ul>l ]
let ol(([H_li*],{style=?String}) -> [H_ol?])
| ([],_) -> []
| (l,s) -> [ <ol (s)>l ]
let display_sitemap (h : Tree) : H_li =
let ch = map h . children with x -> display_sitemap x in
<li>[ <a href=(h . url)>[ '[' !(h . title) ']' ] !(h . boxes); (ul ch) ]
let boxes_of (Page -> [H_ul?])
<page ..>[ (items::Item | _)*] & p ->
let toc = transform items with
| <box title=t link=l ..>_ | <halfwidth_box title=t link=l ..>_ ->
[ <li>[ <a href=[ !(url_of_page p) '#' !l ]>t ] ]
in
ul toc
let link_to (<page (r)>[<title>t _* ] & p : Page) : H_a =
let t = match r with
| {new="" ..} -> t @ [ <img src="img/new.gif" alt="(new)" style="border:0">[]]
| _ -> t in
<a href=(url_of_page p)>t
let small_box (x : Flow) : Block = <div class="smallbox">x
let meta (x : Flow) : Block = <div class="meta">x
let box_title (x : Flow, a : String, t : String) : Block =
<div id="box" class="span-20">[ <h2>[<a name=a>t ] !x ]
let box (x : Flow) : Block = <div id="box" class="span-20">[ !x ]
let hwbox_title (x : Flow, a : String, t : String, pos : ("left" | "right"))
: Block =
let class_css = (match pos with "left" -> "span-10 border" | "right" ->
"span-10 last") in
<div class=("hwbox " @ class_css)>[ <h2>[<a name=a>t ] !x ]
let hwbox (x : Flow, pos : ("left" | "right")) : Block =
let class_css = (match pos with "left" -> "span-10 border" | "right" ->
"span-10 last") in
<div id="hwbox" class=class_css>[ !x ]
type PageO = Page | []
let button(title : String)(onclick : String) : Inline =
<input type="submit" style="font-size:8px;" value=title onclick=onclick>[]
let button_id(id : String)(title : String)(onclick : String)(style : String)
: Inline =
<input type="submit" id=id
style=("font-size:8px;"@style) value=title
onclick=onclick>[]
let demo(no : Int)(name : String)(prefix : String)(txt : String) : Flow =
let n = [ 'a' !name '_' ] in
let prefix = if prefix = "" then "" else [ 'a' !prefix '_' ] in
[ !(if (no = 1) then [<script src="demo.js" type="text/javascript">" "]
else [])
<table style="width:100%">[
<tr>[
<td style="width:50%">[
(button_id (n@"btn") "Edit" ("editable('"@n@"','');") "")
(button "Evaluate" ("submit('"@n@"');"))
(button "Default" ("defreq('"@n@"');"))