liquid_cms 0.2.1.1 → 0.2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +7 -0
- data/README.rdoc +15 -1
- data/TODO.rdoc +0 -2
- data/app/controllers/cms/assets_controller.rb +20 -6
- data/app/controllers/cms/components_controller.rb +11 -3
- data/app/controllers/cms/pages_controller.rb +15 -4
- data/app/helpers/cms/common_helper.rb +31 -31
- data/app/liquid/cms_paperclip_extension.rb +75 -3
- data/app/models/cms/asset.rb +1 -1
- data/app/models/cms/component.rb +3 -3
- data/app/views/cms/assets/_form.html.erb +1 -1
- data/app/views/cms/assets/update.js.rjs +1 -0
- data/app/views/cms/components/update.js.rjs +1 -0
- data/app/views/cms/pages/_form.html.erb +1 -1
- data/app/views/cms/pages/update.js.rjs +1 -0
- data/app/views/layouts/cms.html.erb +4 -3
- data/generators/liquid_cms/liquid_cms_generator.rb +1 -0
- data/generators/liquid_cms/templates/config/locales/cms/en.yml +4 -0
- data/generators/liquid_cms/templates/migration_rev2.rb +13 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +16 -20
- data/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.css +68 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.js +2197 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/lib/overlay.js +51 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/lib/runmode.js +27 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/clike.js +247 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/index.html +102 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/clojure.js +207 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/index.html +85 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/LICENSE +22 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/coffeescript.js +325 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/index.html +722 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/css/css.js +124 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/css/index.html +56 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.css +3 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.js +13 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/index.html +99 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/haskell.js +242 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/index.html +60 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/htmlmixed.js +79 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/index.html +52 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/index.html +78 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/javascript.js +352 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/index.html +38 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/jinja2.js +42 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/index.html +72 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/lua.js +140 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/index.html +340 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.css +10 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.js +230 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/index.html +33 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/ntriples.js +172 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/LICENSE +7 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/index.html +49 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/pascal.js +138 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/php/index.html +49 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/php/php.js +116 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/index.html +63 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/plsql.js +217 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/LICENSE.txt +21 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/index.html +123 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/python.js +320 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/LICENSE +24 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/index.html +74 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/r.js +141 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/index.html +526 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.css +75 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.js +333 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/LICENSE +24 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/index.html +172 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/ruby.js +195 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/index.html +65 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/scheme.js +202 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/index.html +56 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/smalltalk.js +122 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/index.html +41 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/sparql.js +143 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/index.html +96 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/stex.js +167 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/index.html +103 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/velocity.js +146 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/index.html +42 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/xml.js +231 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/index.html +60 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/xmlpure.js +481 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/index.html +68 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/yaml.js +95 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/cobalt.css +17 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/default.css +19 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/eclipse.css +24 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/elegant.css +9 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/neat.css +8 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/theme/night.css +20 -0
- data/generators/liquid_cms/templates/public/cms/javascripts/cms.js +1 -1
- data/generators/liquid_cms/templates/public/cms/javascripts/codemirror_custom.js +96 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/codemirror_changes.css +26 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/liquid.css +7 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/simple_form.css +0 -8
- data/lib/liquid_cms/version.rb +1 -1
- data/liquid_cms.gemspec +0 -1
- data/test/functional/assets_controller_test.rb +35 -20
- data/test/functional/components_controller_test.rb +15 -5
- data/test/functional/pages_controller_test.rb +19 -6
- data/test/rails_app/config/environment.rb +1 -1
- data/test/rails_app/config/locales/cms/en.yml +19 -4
- data/test/rails_app/db/migrate/20110511161859_create_liquid_cms_upgrade_rev2.rb +13 -0
- data/test/unit/asset_test.rb +1 -1
- metadata +100 -58
- data/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +0 -55
- data/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +0 -158
- data/generators/liquid_cms/templates/public/cms/codemirror/css/font.js +0 -15
- data/generators/liquid_cms/templates/public/cms/codemirror/css/jscolors.css +0 -59
- data/generators/liquid_cms/templates/public/cms/codemirror/css/sparqlcolors.css +0 -43
- data/generators/liquid_cms/templates/public/cms/codemirror/css/xmlcolors.css +0 -55
- data/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +0 -582
- data/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +0 -1671
- data/generators/liquid_cms/templates/public/cms/codemirror/js/highlight.js +0 -68
- data/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +0 -81
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +0 -161
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsedummy.js +0 -32
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsehtmlmixed.js +0 -93
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +0 -359
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +0 -162
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsexml.js +0 -291
- data/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +0 -699
- data/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +0 -159
- data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenize.js +0 -57
- data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +0 -174
- data/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +0 -413
- data/generators/liquid_cms/templates/public/cms/codemirror/js/unittests.js +0 -44
- data/generators/liquid_cms/templates/public/cms/codemirror/js/util.js +0 -133
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
CodeMirror.defineMode("sparql", function(config) {
|
|
2
|
+
var indentUnit = config.indentUnit;
|
|
3
|
+
var curPunc;
|
|
4
|
+
|
|
5
|
+
function wordRegexp(words) {
|
|
6
|
+
return new RegExp("^(?:" + words.join("|") + ")$", "i");
|
|
7
|
+
}
|
|
8
|
+
var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
|
|
9
|
+
"isblank", "isliteral", "union", "a"]);
|
|
10
|
+
var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
|
|
11
|
+
"ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
|
|
12
|
+
"graph", "by", "asc", "desc"]);
|
|
13
|
+
var operatorChars = /[*+\-<>=&|]/;
|
|
14
|
+
|
|
15
|
+
function tokenBase(stream, state) {
|
|
16
|
+
var ch = stream.next();
|
|
17
|
+
curPunc = null;
|
|
18
|
+
if (ch == "$" || ch == "?") {
|
|
19
|
+
stream.match(/^[\w\d]*/);
|
|
20
|
+
return "variable-2";
|
|
21
|
+
}
|
|
22
|
+
else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
|
|
23
|
+
stream.match(/^[^\s\u00a0>]*>?/);
|
|
24
|
+
return "atom";
|
|
25
|
+
}
|
|
26
|
+
else if (ch == "\"" || ch == "'") {
|
|
27
|
+
state.tokenize = tokenLiteral(ch);
|
|
28
|
+
return state.tokenize(stream, state);
|
|
29
|
+
}
|
|
30
|
+
else if (/[{}\(\),\.;\[\]]/.test(ch)) {
|
|
31
|
+
curPunc = ch;
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
else if (ch == "#") {
|
|
35
|
+
stream.skipToEnd();
|
|
36
|
+
return "comment";
|
|
37
|
+
}
|
|
38
|
+
else if (operatorChars.test(ch)) {
|
|
39
|
+
stream.eatWhile(operatorChars);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
else if (ch == ":") {
|
|
43
|
+
stream.eatWhile(/[\w\d\._\-]/);
|
|
44
|
+
return "atom";
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
stream.eatWhile(/[_\w\d]/);
|
|
48
|
+
if (stream.eat(":")) {
|
|
49
|
+
stream.eatWhile(/[\w\d_\-]/);
|
|
50
|
+
return "atom";
|
|
51
|
+
}
|
|
52
|
+
var word = stream.current(), type;
|
|
53
|
+
if (ops.test(word))
|
|
54
|
+
return null;
|
|
55
|
+
else if (keywords.test(word))
|
|
56
|
+
return "keyword";
|
|
57
|
+
else
|
|
58
|
+
return "variable";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function tokenLiteral(quote) {
|
|
63
|
+
return function(stream, state) {
|
|
64
|
+
var escaped = false, ch;
|
|
65
|
+
while ((ch = stream.next()) != null) {
|
|
66
|
+
if (ch == quote && !escaped) {
|
|
67
|
+
state.tokenize = tokenBase;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
escaped = !escaped && ch == "\\";
|
|
71
|
+
}
|
|
72
|
+
return "string";
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function pushContext(state, type, col) {
|
|
77
|
+
state.context = {prev: state.context, indent: state.indent, col: col, type: type};
|
|
78
|
+
}
|
|
79
|
+
function popContext(state) {
|
|
80
|
+
state.indent = state.context.indent;
|
|
81
|
+
state.context = state.context.prev;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
startState: function(base) {
|
|
86
|
+
return {tokenize: tokenBase,
|
|
87
|
+
context: null,
|
|
88
|
+
indent: 0,
|
|
89
|
+
col: 0};
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
token: function(stream, state) {
|
|
93
|
+
if (stream.sol()) {
|
|
94
|
+
if (state.context && state.context.align == null) state.context.align = false;
|
|
95
|
+
state.indent = stream.indentation();
|
|
96
|
+
}
|
|
97
|
+
if (stream.eatSpace()) return null;
|
|
98
|
+
var style = state.tokenize(stream, state);
|
|
99
|
+
|
|
100
|
+
if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
|
|
101
|
+
state.context.align = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (curPunc == "(") pushContext(state, ")", stream.column());
|
|
105
|
+
else if (curPunc == "[") pushContext(state, "]", stream.column());
|
|
106
|
+
else if (curPunc == "{") pushContext(state, "}", stream.column());
|
|
107
|
+
else if (/[\]\}\)]/.test(curPunc)) {
|
|
108
|
+
while (state.context && state.context.type == "pattern") popContext(state);
|
|
109
|
+
if (state.context && curPunc == state.context.type) popContext(state);
|
|
110
|
+
}
|
|
111
|
+
else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
|
|
112
|
+
else if (/atom|string|variable/.test(style) && state.context) {
|
|
113
|
+
if (/[\}\]]/.test(state.context.type))
|
|
114
|
+
pushContext(state, "pattern", stream.column());
|
|
115
|
+
else if (state.context.type == "pattern" && !state.context.align) {
|
|
116
|
+
state.context.align = true;
|
|
117
|
+
state.context.col = stream.column();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return style;
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
indent: function(state, textAfter) {
|
|
125
|
+
var firstChar = textAfter && textAfter.charAt(0);
|
|
126
|
+
var context = state.context;
|
|
127
|
+
if (/[\]\}]/.test(firstChar))
|
|
128
|
+
while (context && context.type == "pattern") context = context.prev;
|
|
129
|
+
|
|
130
|
+
var closing = context && firstChar == context.type;
|
|
131
|
+
if (!context)
|
|
132
|
+
return 0;
|
|
133
|
+
else if (context.type == "pattern")
|
|
134
|
+
return context.col;
|
|
135
|
+
else if (context.align)
|
|
136
|
+
return context.col + (closing ? 0 : 1);
|
|
137
|
+
else
|
|
138
|
+
return context.indent + (closing ? 0 : indentUnit);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
CodeMirror.defineMIME("application/x-sparql-query", "sparql");
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>CodeMirror 2: sTeX mode</title>
|
|
5
|
+
<link rel="stylesheet" href="../../lib/codemirror.css">
|
|
6
|
+
<script src="../../lib/codemirror.js"></script>
|
|
7
|
+
<script src="stex.js"></script>
|
|
8
|
+
<link rel="stylesheet" href="../../theme/default.css">
|
|
9
|
+
<style>.CodeMirror {background: #f8f8f8;}</style>
|
|
10
|
+
<link rel="stylesheet" href="../../css/docs.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<h1>CodeMirror 2: sTeX mode</h1>
|
|
14
|
+
<form><textarea id="code" name="code">
|
|
15
|
+
\begin{module}[id=bbt-size]
|
|
16
|
+
\importmodule[balanced-binary-trees]{balanced-binary-trees}
|
|
17
|
+
\importmodule[\KWARCslides{dmath/en/cardinality}]{cardinality}
|
|
18
|
+
|
|
19
|
+
\begin{frame}
|
|
20
|
+
\frametitle{Size Lemma for Balanced Trees}
|
|
21
|
+
\begin{itemize}
|
|
22
|
+
\item
|
|
23
|
+
\begin{assertion}[id=size-lemma,type=lemma]
|
|
24
|
+
Let $G=\tup{V,E}$ be a \termref[cd=binary-trees]{balanced binary tree}
|
|
25
|
+
of \termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set
|
|
26
|
+
$\defeq{\livar{V}i}{\setst{\inset{v}{V}}{\gdepth{v} = i}}$ of
|
|
27
|
+
\termref[cd=graphs-intro,name=node]{nodes} at
|
|
28
|
+
\termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has
|
|
29
|
+
\termref[cd=cardinality,name=cardinality]{cardinality} $\power2i$.
|
|
30
|
+
\end{assertion}
|
|
31
|
+
\item
|
|
32
|
+
\begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}
|
|
33
|
+
\begin{spfcases}{We have to consider two cases}
|
|
34
|
+
\begin{spfcase}{$i=0$}
|
|
35
|
+
\begin{spfstep}[display=flow]
|
|
36
|
+
then $\livar{V}i=\set{\livar{v}r}$, where $\livar{v}r$ is the root, so
|
|
37
|
+
$\eq{\card{\livar{V}0},\card{\set{\livar{v}r}},1,\power20}$.
|
|
38
|
+
\end{spfstep}
|
|
39
|
+
\end{spfcase}
|
|
40
|
+
\begin{spfcase}{$i>0$}
|
|
41
|
+
\begin{spfstep}[display=flow]
|
|
42
|
+
then $\livar{V}{i-1}$ contains $\power2{i-1}$ vertexes
|
|
43
|
+
\begin{justification}[method=byIH](IH)\end{justification}
|
|
44
|
+
\end{spfstep}
|
|
45
|
+
\begin{spfstep}
|
|
46
|
+
By the \begin{justification}[method=byDef]definition of a binary
|
|
47
|
+
tree\end{justification}, each $\inset{v}{\livar{V}{i-1}}$ is a leaf or has
|
|
48
|
+
two children that are at depth $i$.
|
|
49
|
+
\end{spfstep}
|
|
50
|
+
\begin{spfstep}
|
|
51
|
+
As $G$ is \termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\gdepth{G}=n>i$, $\livar{V}{i-1}$ cannot contain
|
|
52
|
+
leaves.
|
|
53
|
+
\end{spfstep}
|
|
54
|
+
\begin{spfstep}[type=conclusion]
|
|
55
|
+
Thus $\eq{\card{\livar{V}i},{\atimes[cdot]{2,\card{\livar{V}{i-1}}}},{\atimes[cdot]{2,\power2{i-1}}},\power2i}$.
|
|
56
|
+
\end{spfstep}
|
|
57
|
+
\end{spfcase}
|
|
58
|
+
\end{spfcases}
|
|
59
|
+
\end{sproof}
|
|
60
|
+
\item
|
|
61
|
+
\begin{assertion}[id=fbbt,type=corollary]
|
|
62
|
+
A fully balanced tree of depth $d$ has $\power2{d+1}-1$ nodes.
|
|
63
|
+
\end{assertion}
|
|
64
|
+
\item
|
|
65
|
+
\begin{sproof}[for=fbbt,id=fbbt-pf]{}
|
|
66
|
+
\begin{spfstep}
|
|
67
|
+
Let $\defeq{G}{\tup{V,E}}$ be a fully balanced tree
|
|
68
|
+
\end{spfstep}
|
|
69
|
+
\begin{spfstep}
|
|
70
|
+
Then $\card{V}=\Sumfromto{i}1d{\power2i}= \power2{d+1}-1$.
|
|
71
|
+
\end{spfstep}
|
|
72
|
+
\end{sproof}
|
|
73
|
+
\end{itemize}
|
|
74
|
+
\end{frame}
|
|
75
|
+
\begin{note}
|
|
76
|
+
\begin{omtext}[type=conclusion,for=binary-tree]
|
|
77
|
+
This shows that balanced binary trees grow in breadth very quickly, a consequence of
|
|
78
|
+
this is that they are very shallow (and this compute very fast), which is the essence of
|
|
79
|
+
the next result.
|
|
80
|
+
\end{omtext}
|
|
81
|
+
\end{note}
|
|
82
|
+
\end{module}
|
|
83
|
+
|
|
84
|
+
%%% Local Variables:
|
|
85
|
+
%%% mode: LaTeX
|
|
86
|
+
%%% TeX-master: "all"
|
|
87
|
+
%%% End: \end{document}
|
|
88
|
+
</textarea></form>
|
|
89
|
+
<script>
|
|
90
|
+
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<p><strong>MIME types defined:</strong> <code>text/stex</code>.</p>
|
|
94
|
+
|
|
95
|
+
</body>
|
|
96
|
+
</html>
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
|
|
3
|
+
* Licence: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
|
|
7
|
+
{
|
|
8
|
+
function pushCommand(state, command) {
|
|
9
|
+
state.cmdState.push(command);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function peekCommand(state) {
|
|
13
|
+
if (state.cmdState.length>0)
|
|
14
|
+
return state.cmdState[state.cmdState.length-1];
|
|
15
|
+
else
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function popCommand(state) {
|
|
20
|
+
if (state.cmdState.length>0) {
|
|
21
|
+
var plug = state.cmdState.pop();
|
|
22
|
+
plug.closeBracket();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function applyMostPowerful(state) {
|
|
27
|
+
var context = state.cmdState;
|
|
28
|
+
for (var i = context.length - 1; i >= 0; i--) {
|
|
29
|
+
var plug = context[i];
|
|
30
|
+
if (plug.name=="DEFAULT")
|
|
31
|
+
continue;
|
|
32
|
+
return plug.styleIdentifier();
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
|
|
38
|
+
return function () {
|
|
39
|
+
this.name=pluginName;
|
|
40
|
+
this.bracketNo = 0;
|
|
41
|
+
this.style=cmdStyle;
|
|
42
|
+
this.styles = styles;
|
|
43
|
+
this.brackets = brackets;
|
|
44
|
+
|
|
45
|
+
this.styleIdentifier = function(content) {
|
|
46
|
+
if (this.bracketNo<=this.styles.length)
|
|
47
|
+
return this.styles[this.bracketNo-1];
|
|
48
|
+
else
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
this.openBracket = function(content) {
|
|
52
|
+
this.bracketNo++;
|
|
53
|
+
return "bracket";
|
|
54
|
+
};
|
|
55
|
+
this.closeBracket = function(content) {
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
var plugins = new Array();
|
|
61
|
+
|
|
62
|
+
plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
|
|
63
|
+
plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
|
|
64
|
+
plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
65
|
+
plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
66
|
+
plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
67
|
+
|
|
68
|
+
plugins["DEFAULT"] = function () {
|
|
69
|
+
this.name="DEFAULT";
|
|
70
|
+
this.style="tag";
|
|
71
|
+
|
|
72
|
+
this.styleIdentifier = function(content) {
|
|
73
|
+
};
|
|
74
|
+
this.openBracket = function(content) {
|
|
75
|
+
};
|
|
76
|
+
this.closeBracket = function(content) {
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function setState(state, f) {
|
|
81
|
+
state.f = f;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normal(source, state) {
|
|
85
|
+
if (source.match(/^\\[a-z]+/)) {
|
|
86
|
+
var cmdName = source.current();
|
|
87
|
+
cmdName = cmdName.substr(1, cmdName.length-1);
|
|
88
|
+
var plug = plugins[cmdName];
|
|
89
|
+
if (typeof(plug) == 'undefined') {
|
|
90
|
+
plug = plugins["DEFAULT"];
|
|
91
|
+
}
|
|
92
|
+
plug = new plug();
|
|
93
|
+
pushCommand(state, plug);
|
|
94
|
+
setState(state, beginParams);
|
|
95
|
+
return plug.style;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var ch = source.next();
|
|
99
|
+
if (ch == "%") {
|
|
100
|
+
setState(state, inCComment);
|
|
101
|
+
return "comment";
|
|
102
|
+
}
|
|
103
|
+
else if (ch=='}' || ch==']') {
|
|
104
|
+
plug = peekCommand(state);
|
|
105
|
+
if (plug) {
|
|
106
|
+
plug.closeBracket(ch);
|
|
107
|
+
setState(state, beginParams);
|
|
108
|
+
} else
|
|
109
|
+
return "error";
|
|
110
|
+
return "bracket";
|
|
111
|
+
} else if (ch=='{' || ch=='[') {
|
|
112
|
+
plug = plugins["DEFAULT"];
|
|
113
|
+
plug = new plug();
|
|
114
|
+
pushCommand(state, plug);
|
|
115
|
+
return "bracket";
|
|
116
|
+
}
|
|
117
|
+
else if (/\d/.test(ch)) {
|
|
118
|
+
source.eatWhile(/[\w.%]/);
|
|
119
|
+
return "atom";
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
source.eatWhile(/[\w-_]/);
|
|
123
|
+
return applyMostPowerful(state);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function inCComment(source, state) {
|
|
128
|
+
source.skipToEnd();
|
|
129
|
+
setState(state, normal);
|
|
130
|
+
return "comment";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function beginParams(source, state) {
|
|
134
|
+
var ch = source.peek();
|
|
135
|
+
if (ch == '{' || ch == '[') {
|
|
136
|
+
var lastPlug = peekCommand(state);
|
|
137
|
+
var style = lastPlug.openBracket(ch);
|
|
138
|
+
source.eat(ch);
|
|
139
|
+
setState(state, normal);
|
|
140
|
+
return "bracket";
|
|
141
|
+
}
|
|
142
|
+
if (/[ \t\r]/.test(ch)) {
|
|
143
|
+
source.eat(ch);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
setState(state, normal);
|
|
147
|
+
lastPlug = peekCommand(state);
|
|
148
|
+
if (lastPlug) {
|
|
149
|
+
popCommand(state);
|
|
150
|
+
}
|
|
151
|
+
return normal(source, state);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
startState: function() { return { f:normal, cmdState:[] }; },
|
|
156
|
+
copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },
|
|
157
|
+
|
|
158
|
+
token: function(stream, state) {
|
|
159
|
+
var t = state.f(stream, state);
|
|
160
|
+
var w = stream.current();
|
|
161
|
+
return t;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
CodeMirror.defineMIME("text/x-stex", "stex");
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>CodeMirror 2: Velocity mode</title>
|
|
5
|
+
<link rel="stylesheet" href="../../lib/codemirror.css">
|
|
6
|
+
<script src="../../lib/codemirror.js"></script>
|
|
7
|
+
<script src="velocity.js"></script>
|
|
8
|
+
<link rel="stylesheet" href="../../theme/night.css">
|
|
9
|
+
<style>.CodeMirror {border: 1px solid black;}</style>
|
|
10
|
+
<link rel="stylesheet" href="../../css/docs.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<h1>CodeMirror 2: Velocity mode</h1>
|
|
14
|
+
<form><textarea id="code" name="code">
|
|
15
|
+
## Velocity Code Demo
|
|
16
|
+
#*
|
|
17
|
+
based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )
|
|
18
|
+
August 2011
|
|
19
|
+
*#
|
|
20
|
+
|
|
21
|
+
#*
|
|
22
|
+
This is a multiline comment.
|
|
23
|
+
This is the second line
|
|
24
|
+
*#
|
|
25
|
+
|
|
26
|
+
#[[ hello steve
|
|
27
|
+
This has invalid syntax that would normally need "poor man's escaping" like:
|
|
28
|
+
|
|
29
|
+
#define()
|
|
30
|
+
|
|
31
|
+
${blah
|
|
32
|
+
]]#
|
|
33
|
+
|
|
34
|
+
#include( "disclaimer.txt" "opinion.txt" )
|
|
35
|
+
#include( $foo $bar )
|
|
36
|
+
|
|
37
|
+
#parse( "lecorbusier.vm" )
|
|
38
|
+
#parse( $foo )
|
|
39
|
+
|
|
40
|
+
#evaluate( 'string with VTL #if(true)will be displayed#end' )
|
|
41
|
+
|
|
42
|
+
#define( $hello ) Hello $who #end #set( $who = "World!") $hello ## displays Hello World!
|
|
43
|
+
|
|
44
|
+
#foreach( $customer in $customerList )
|
|
45
|
+
|
|
46
|
+
$foreach.count $customer.Name
|
|
47
|
+
|
|
48
|
+
#if( $foo == ${bar})
|
|
49
|
+
it's true!
|
|
50
|
+
#break
|
|
51
|
+
#{else}
|
|
52
|
+
it's not!
|
|
53
|
+
#stop
|
|
54
|
+
#end
|
|
55
|
+
|
|
56
|
+
#if ($foreach.parent.hasNext)
|
|
57
|
+
$velocityCount
|
|
58
|
+
#end
|
|
59
|
+
#end
|
|
60
|
+
|
|
61
|
+
$someObject.getValues("this is a string split
|
|
62
|
+
across lines")
|
|
63
|
+
|
|
64
|
+
#macro( tablerows $color $somelist )
|
|
65
|
+
#foreach( $something in $somelist )
|
|
66
|
+
<tr><td bgcolor=$color>$something</td></tr>
|
|
67
|
+
#end
|
|
68
|
+
#end
|
|
69
|
+
|
|
70
|
+
#tablerows("red" ["dadsdf","dsa"])
|
|
71
|
+
|
|
72
|
+
Variable reference: #set( $monkey = $bill )
|
|
73
|
+
String literal: #set( $monkey.Friend = 'monica' )
|
|
74
|
+
Property reference: #set( $monkey.Blame = $whitehouse.Leak )
|
|
75
|
+
Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )
|
|
76
|
+
Number literal: #set( $monkey.Number = 123 )
|
|
77
|
+
Range operator: #set( $monkey.Numbers = [1..3] )
|
|
78
|
+
Object list: #set( $monkey.Say = ["Not", $my, "fault"] )
|
|
79
|
+
Object map: #set( $monkey.Map = {"banana" : "good", "roast beef" : "bad"})
|
|
80
|
+
|
|
81
|
+
The RHS can also be a simple arithmetic expression, such as:
|
|
82
|
+
Addition: #set( $value = $foo + 1 )
|
|
83
|
+
Subtraction: #set( $value = $bar - 1 )
|
|
84
|
+
Multiplication: #set( $value = $foo * $bar )
|
|
85
|
+
Division: #set( $value = $foo / $bar )
|
|
86
|
+
Remainder: #set( $value = $foo % $bar )
|
|
87
|
+
|
|
88
|
+
</textarea></form>
|
|
89
|
+
<script>
|
|
90
|
+
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
|
91
|
+
tabMode: "indent",
|
|
92
|
+
matchBrackets: true,
|
|
93
|
+
theme: "night",
|
|
94
|
+
lineNumbers: true,
|
|
95
|
+
indentUnit: 4,
|
|
96
|
+
mode: "text/velocity"
|
|
97
|
+
});
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>
|
|
101
|
+
|
|
102
|
+
</body>
|
|
103
|
+
</html>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
CodeMirror.defineMode("velocity", function(config) {
|
|
2
|
+
function parseWords(str) {
|
|
3
|
+
var obj = {}, words = str.split(" ");
|
|
4
|
+
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
|
5
|
+
return obj;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
var indentUnit = config.indentUnit
|
|
9
|
+
var keywords = parseWords("#end #else #break #stop #[[ #]] " +
|
|
10
|
+
"#{end} #{else} #{break} #{stop}");
|
|
11
|
+
var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " +
|
|
12
|
+
"#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}");
|
|
13
|
+
var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount");
|
|
14
|
+
var isOperatorChar = /[+\-*&%=<>!?:\/|]/;
|
|
15
|
+
var multiLineStrings =true;
|
|
16
|
+
|
|
17
|
+
function chain(stream, state, f) {
|
|
18
|
+
state.tokenize = f;
|
|
19
|
+
return f(stream, state);
|
|
20
|
+
}
|
|
21
|
+
function tokenBase(stream, state) {
|
|
22
|
+
var beforeParams = state.beforeParams;
|
|
23
|
+
state.beforeParams = false;
|
|
24
|
+
var ch = stream.next();
|
|
25
|
+
// start of string?
|
|
26
|
+
if ((ch == '"' || ch == "'") && state.inParams)
|
|
27
|
+
return chain(stream, state, tokenString(ch));
|
|
28
|
+
// is it one of the special signs []{}().,;? Seperator?
|
|
29
|
+
else if (/[\[\]{}\(\),;\.]/.test(ch)) {
|
|
30
|
+
if (ch == "(" && beforeParams) state.inParams = true;
|
|
31
|
+
else if (ch == ")") state.inParams = false;
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
// start of a number value?
|
|
35
|
+
else if (/\d/.test(ch)) {
|
|
36
|
+
stream.eatWhile(/[\w\.]/);
|
|
37
|
+
return "number";
|
|
38
|
+
}
|
|
39
|
+
// multi line comment?
|
|
40
|
+
else if (ch == "#" && stream.eat("*")) {
|
|
41
|
+
return chain(stream, state, tokenComment);
|
|
42
|
+
}
|
|
43
|
+
// unparsed content?
|
|
44
|
+
else if (ch == "#" && stream.match(/ *\[ *\[/)) {
|
|
45
|
+
return chain(stream, state, tokenUnparsed);
|
|
46
|
+
}
|
|
47
|
+
// single line comment?
|
|
48
|
+
else if (ch == "#" && stream.eat("#")) {
|
|
49
|
+
stream.skipToEnd();
|
|
50
|
+
return "comment";
|
|
51
|
+
}
|
|
52
|
+
// variable?
|
|
53
|
+
else if (ch == "$") {
|
|
54
|
+
stream.eatWhile(/[\w\d\$_\.{}]/);
|
|
55
|
+
// is it one of the specials?
|
|
56
|
+
if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {
|
|
57
|
+
return "keyword";
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
state.beforeParams = true;
|
|
61
|
+
return "builtin";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// is it a operator?
|
|
65
|
+
else if (isOperatorChar.test(ch)) {
|
|
66
|
+
stream.eatWhile(isOperatorChar);
|
|
67
|
+
return "operator";
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// get the whole word
|
|
71
|
+
stream.eatWhile(/[\w\$_{}]/);
|
|
72
|
+
var word = stream.current().toLowerCase();
|
|
73
|
+
// is it one of the listed keywords?
|
|
74
|
+
if (keywords && keywords.propertyIsEnumerable(word))
|
|
75
|
+
return "keyword";
|
|
76
|
+
// is it one of the listed functions?
|
|
77
|
+
if (functions && functions.propertyIsEnumerable(word) ||
|
|
78
|
+
stream.current().match(/^#[a-z0-9_]+ *$/i) && stream.peek()=="(") {
|
|
79
|
+
state.beforeParams = true;
|
|
80
|
+
return "keyword";
|
|
81
|
+
}
|
|
82
|
+
// default: just a "word"
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function tokenString(quote) {
|
|
88
|
+
return function(stream, state) {
|
|
89
|
+
var escaped = false, next, end = false;
|
|
90
|
+
while ((next = stream.next()) != null) {
|
|
91
|
+
if (next == quote && !escaped) {
|
|
92
|
+
end = true;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
escaped = !escaped && next == "\\";
|
|
96
|
+
}
|
|
97
|
+
if (end) state.tokenize = tokenBase;
|
|
98
|
+
return "string";
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function tokenComment(stream, state) {
|
|
103
|
+
var maybeEnd = false, ch;
|
|
104
|
+
while (ch = stream.next()) {
|
|
105
|
+
if (ch == "#" && maybeEnd) {
|
|
106
|
+
state.tokenize = tokenBase;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
maybeEnd = (ch == "*");
|
|
110
|
+
}
|
|
111
|
+
return "comment";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function tokenUnparsed(stream, state) {
|
|
115
|
+
var maybeEnd = 0, ch;
|
|
116
|
+
while (ch = stream.next()) {
|
|
117
|
+
if (ch == "#" && maybeEnd == 2) {
|
|
118
|
+
state.tokenize = tokenBase;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (ch == "]")
|
|
122
|
+
maybeEnd++;
|
|
123
|
+
else if (ch != " ")
|
|
124
|
+
maybeEnd = 0;
|
|
125
|
+
}
|
|
126
|
+
return "meta";
|
|
127
|
+
}
|
|
128
|
+
// Interface
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
startState: function(basecolumn) {
|
|
132
|
+
return {
|
|
133
|
+
tokenize: tokenBase,
|
|
134
|
+
beforeParams: false,
|
|
135
|
+
inParams: false
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
token: function(stream, state) {
|
|
140
|
+
if (stream.eatSpace()) return null;
|
|
141
|
+
return state.tokenize(stream, state);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
CodeMirror.defineMIME("text/velocity", "velocity");
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>CodeMirror 2: XML mode</title>
|
|
5
|
+
<link rel="stylesheet" href="../../lib/codemirror.css">
|
|
6
|
+
<script src="../../lib/codemirror.js"></script>
|
|
7
|
+
<script src="xml.js"></script>
|
|
8
|
+
<link rel="stylesheet" href="../../theme/default.css">
|
|
9
|
+
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
|
10
|
+
<link rel="stylesheet" href="../../css/docs.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<h1>CodeMirror 2: XML mode</h1>
|
|
14
|
+
<form><textarea id="code" name="code">
|
|
15
|
+
<html style="color: green">
|
|
16
|
+
<!-- this is a comment -->
|
|
17
|
+
<head>
|
|
18
|
+
<title>HTML Example</title>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
The indentation tries to be <em>somewhat &quot;do what
|
|
22
|
+
I mean&quot;</em>... but might not match your style.
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
25
|
+
</textarea></form>
|
|
26
|
+
<script>
|
|
27
|
+
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {mode: {name: "xml", htmlMode: true}});
|
|
28
|
+
</script>
|
|
29
|
+
<p>The XML mode supports two configuration parameters:</p>
|
|
30
|
+
<dl>
|
|
31
|
+
<dt><code>htmlMode (boolean)</code></dt>
|
|
32
|
+
<dd>This switches the mode to parse HTML instead of XML. This
|
|
33
|
+
means attributes do not have to be quoted, and some elements
|
|
34
|
+
(such as <code>br</code>) do not require a closing tag.</dd>
|
|
35
|
+
<dt><code>alignCDATA (boolean)</code></dt>
|
|
36
|
+
<dd>Setting this to true will force the opening tag of CDATA
|
|
37
|
+
blocks to not be indented.</dd>
|
|
38
|
+
</dl>
|
|
39
|
+
|
|
40
|
+
<p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
|
|
41
|
+
</body>
|
|
42
|
+
</html>
|