Improved new documentation
diff --git a/Gruntfile.js b/Gruntfile.js
index bec3fba..7e9edf8 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -119,7 +119,7 @@
grunt.loadNpmTasks('grunt-contrib-requirejs');
grunt.registerTask('default', ['requirejs']);
-
+ grunt.registerTask('img', ['imagemin','copy']);
grunt.registerTask('css', ['sass']);
grunt.registerTask(
'default',
diff --git a/dev/scss/base.scss b/dev/scss/base.scss
index 42aba2c..1d3d26a 100644
--- a/dev/scss/base.scss
+++ b/dev/scss/base.scss
@@ -25,12 +25,10 @@
font-size: 12pt;
}
-.intro p {
- text-shadow: $light-shadow
-}
a {
- &[href^="http://"]:after {
+ &[href^="http://"]:after,
+ &[href^="https://"]:after {
font-family: FontAwesome;
content: " " + $fa-extlink;
font-size: 75%;
@@ -47,62 +45,3 @@
}
}
}
-
-main {
- margin: {
- left: $standard-margin;
- right: $standard-margin; // Todo: -16px
- }
- &.embedded {
- margin: {
- left: 14px;
- right: 14px;
- }
- }
- p {
- text-align: justify;
- hyphens: auto;
- }
-
-/*
- > section > p, > p {
- a {
- border-radius: 6px;
- padding: 0 .3em;
- background-color: $choose-bg;
- text-shadow: light-shadow;
- color: $light-green;
- &:hover {
- color: $dark-green;
- text-shadow: none;
- background-color: $light-green;
- }
- }
- }
-*/
-}
-/*
-blockquote {
- border-radius: 12px;
- margin: 0;
- text-indent: 0;
- padding: 1em;
- border-left: {
- color: $dark-grey;
- style: solid;
- width: 1em;
- }
- background-color: $light-grey;
- &.warning {
- border-left-color: $dark-orange;
- }
- &.exception {
- border-left-color: red;
- }
-}
-*/
-
-div.intro {
- width: 70%;
- min-width: 600px;
-}
\ No newline at end of file
diff --git a/dev/scss/footer/footer.scss b/dev/scss/footer/footer.scss
index 2cfd773..0ce1ae4 100644
--- a/dev/scss/footer/footer.scss
+++ b/dev/scss/footer/footer.scss
@@ -5,9 +5,11 @@
position: absolute;
background-color: $dark-grey;
bottom: 0;
+ font-size: 70%;
width: 100%;
- text-align: center;
+ text-align: right;
a:link {
+ margin: 0 .5em;
color: $light-grey;
&:hover {
color: $nearly-white;
diff --git a/dev/scss/main/alertify.scss b/dev/scss/main/alertify.scss
index 0eb3194..df1225c 100644
--- a/dev/scss/main/alertify.scss
+++ b/dev/scss/main/alertify.scss
@@ -1,4 +1,6 @@
@import "../util";
+@import "alertify/alertify-core";
+@import "alertify/alertify-default";
/*
article.alertify-log {
diff --git a/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake84934ky.rbc b/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake84934ky.rbc
new file mode 100644
index 0000000..27909e1
--- /dev/null
+++ b/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake84934ky.rbc
Binary files differ
diff --git a/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake8493ras.rbc b/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake8493ras.rbc
new file mode 100644
index 0000000..773e743
--- /dev/null
+++ b/dev/scss/main/alertify/.sass-cache/600d657f6ac2358f30ba6bc0ab4cd7ffb6194ced/flymake8493ras.rbc
Binary files differ
diff --git a/dev/scss/main/alertify/alertify-core.scss b/dev/scss/main/alertify/alertify-core.scss
new file mode 100644
index 0000000..5978b4f
--- /dev/null
+++ b/dev/scss/main/alertify/alertify-core.scss
@@ -0,0 +1,137 @@
+.alertify,
+.alertify-show,
+.alertify-log {
+ -webkit-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275);
+ -moz-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275);
+ -ms-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275);
+ -o-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275);
+ transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); /* easeOutBack */
+}
+.alertify-hide {
+ -webkit-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -moz-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -ms-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -o-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */
+}
+.alertify-log-hide {
+ -webkit-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -moz-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -ms-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ -o-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045);
+ transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */
+}
+.alertify-cover {
+ position: fixed; z-index: 99999;
+ top: 0; right: 0; bottom: 0; left: 0;
+ background-color:white;
+ filter:alpha(opacity=0);
+ opacity:0;
+}
+.alertify-cover-hidden {
+ display: none;
+}
+.alertify {
+ position: fixed; z-index: 99999;
+ top: 50px; left: 50%;
+ width: 550px;
+ margin-left: -275px;
+ opacity: 1;
+}
+.alertify-hidden {
+ -webkit-transform: translate(0,-150px);
+ -moz-transform: translate(0,-150px);
+ -ms-transform: translate(0,-150px);
+ -o-transform: translate(0,-150px);
+ transform: translate(0,-150px);
+ opacity: 0;
+ display: none;
+}
+/* overwrite display: none; for everything except IE6-8 */
+:root *> .alertify-hidden {
+ display: block;
+ visibility: hidden;
+}
+.alertify-logs {
+ position: fixed;
+ z-index: 5000;
+ bottom: 10px;
+ right: 10px;
+ width: 300px;
+}
+.alertify-logs-hidden {
+ display: none;
+}
+.alertify-log {
+ display: block;
+ margin-top: 10px;
+ position: relative;
+ right: -300px;
+ opacity: 0;
+}
+.alertify-log-show {
+ right: 0;
+ opacity: 1;
+}
+.alertify-log-hide {
+ -webkit-transform: translate(300px, 0);
+ -moz-transform: translate(300px, 0);
+ -ms-transform: translate(300px, 0);
+ -o-transform: translate(300px, 0);
+ transform: translate(300px, 0);
+ opacity: 0;
+}
+.alertify-dialog {
+ padding: 25px;
+}
+.alertify-resetFocus {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+.alertify-inner {
+ text-align: center;
+}
+.alertify-text {
+ margin-bottom: 15px;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 100%;
+}
+.alertify-buttons {
+}
+.alertify-button,
+.alertify-button:hover,
+.alertify-button:active,
+.alertify-button:visited {
+ background: none;
+ text-decoration: none;
+ border: none;
+ /* line-height and font-size for input button */
+ line-height: 1.5;
+ font-size: 100%;
+ display: inline-block;
+ cursor: pointer;
+ margin-left: 5px;
+}
+
+@media only screen and (max-width: 680px) {
+ .alertify,
+ .alertify-logs {
+ width: 90%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .alertify {
+ left: 5%;
+ margin: 0;
+ }
+}
diff --git a/dev/scss/main/alertify/alertify-default.scss b/dev/scss/main/alertify/alertify-default.scss
new file mode 100644
index 0000000..00524cd
--- /dev/null
+++ b/dev/scss/main/alertify/alertify-default.scss
@@ -0,0 +1,81 @@
+/**
+ * Default Look and Feel
+ */
+.alertify,
+.alertify-log {
+ font-family: sans-serif;
+}
+.alertify {
+ background: #FFF;
+ border: 10px solid #333; /* browsers that don't support rgba */
+ border: 10px solid rgba(0,0,0,.7);
+ border-radius: 8px;
+ box-shadow: 0 3px 3px rgba(0,0,0,.3);
+ -webkit-background-clip: padding; /* Safari 4? Chrome 6? */
+ -moz-background-clip: padding; /* Firefox 3.6 */
+ background-clip: padding-box; /* Firefox 4, Safari 5, Opera 10, IE 9 */
+}
+.alertify-text {
+ border: 1px solid #CCC;
+ padding: 10px;
+ border-radius: 4px;
+}
+.alertify-button {
+ border-radius: 4px;
+ color: #FFF;
+ font-weight: bold;
+ padding: 6px 15px;
+ text-decoration: none;
+ text-shadow: 1px 1px 0 rgba(0,0,0,.5);
+ box-shadow: inset 0 1px 0 0 rgba(255,255,255,.5);
+ background-image: -webkit-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0));
+ background-image: -moz-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0));
+ background-image: -ms-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0));
+ background-image: -o-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0));
+ background-image: linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0));
+}
+.alertify-button:hover,
+.alertify-button:focus {
+ outline: none;
+ background-image: -webkit-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0));
+ background-image: -moz-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0));
+ background-image: -ms-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0));
+ background-image: -o-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0));
+ background-image: linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0));
+}
+.alertify-button:focus {
+ box-shadow: 0 0 15px #2B72D5;
+}
+.alertify-button:active {
+ position: relative;
+ box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
+}
+.alertify-button-cancel,
+.alertify-button-cancel:hover,
+.alertify-button-cancel:focus {
+ background-color: #FE1A00;
+ border: 1px solid #D83526;
+}
+.alertify-button-ok,
+.alertify-button-ok:hover,
+.alertify-button-ok:focus {
+ background-color: #5CB811;
+ border: 1px solid #3B7808;
+}
+
+.alertify-log {
+ background: #1F1F1F;
+ background: rgba(0,0,0,.9);
+ padding: 15px;
+ border-radius: 4px;
+ color: #FFF;
+ text-shadow: -1px -1px 0 rgba(0,0,0,.5);
+}
+.alertify-log-error {
+ background: #FE1A00;
+ background: rgba(254,26,0,.9);
+}
+.alertify-log-success {
+ background: #5CB811;
+ background: rgba(92,184,17,.9);
+}
\ No newline at end of file
diff --git a/dev/scss/main/main.scss b/dev/scss/main/main.scss
index ea569fa..9cadd4b 100644
--- a/dev/scss/main/main.scss
+++ b/dev/scss/main/main.scss
@@ -8,5 +8,74 @@
@import "sidebar"; // Navigation on the left side
@import "tutorial"; // Embedded and non-embedded tutorial
@import "alertify";
-@import "alertify/alertify.core.css";
-@import "alertify/alertify.default.css";
+
+div.intro {
+ width: 70%;
+ min-width: 600px;
+}
+
+
+main {
+ margin: {
+ left: $standard-margin;
+ right: $standard-margin; // Todo: -16px
+ }
+ padding-bottom: 20pt;
+ &.embedded {
+ margin: {
+ left: 14px;
+ right: 14px;
+ }
+ }
+ p {
+ text-align: justify;
+ hyphens: auto;
+ }
+
+/*
+ > section > p, > p {
+ a {
+ border-radius: 6px;
+ padding: 0 .3em;
+ background-color: $choose-bg;
+ text-shadow: light-shadow;
+ color: $light-green;
+ &:hover {
+ color: $dark-green;
+ text-shadow: none;
+ background-color: $light-green;
+ }
+ }
+ }
+*/
+}
+
+blockquote {
+ border-radius: $standard-border-radius;
+ padding: 2pt 5pt 2pt 20pt;
+ margin: 0;
+ border-left: 5px solid $ids-blue-1;
+ background-color: $ids-blue-2;
+ color: $ids-blue-1;
+}
+
+/*
+blockquote {
+ border-radius: 12px;
+ margin: 0;
+ text-indent: 0;
+ padding: 1em;
+ border-left: {
+ color: $dark-grey;
+ style: solid;
+ width: 1em;
+ }
+ background-color: $light-grey;
+ &.warning {
+ border-left-color: $dark-orange;
+ }
+ &.exception {
+ border-left-color: red;
+ }
+}
+*/
diff --git a/dev/scss/main/sidebar.scss b/dev/scss/main/sidebar.scss
index 7c74912..b454055 100644
--- a/dev/scss/main/sidebar.scss
+++ b/dev/scss/main/sidebar.scss
@@ -68,6 +68,20 @@
> a {
padding: $item-padding;
}
+
+ li.folded {
+ &.active ul {
+ display: block;
+ }
+ ul {
+ display: none;
+ }
+ }
+
+ &.active > a:link {
+ @include choose-active;
+ }
+
> a:link {
@include choose-item;
border-right: {
@@ -84,9 +98,6 @@
transition: none;
@include choose-hover;
}
- &.active, &:active {
- @include choose-active;
- }
}
h3 {
font: {
diff --git a/dev/scss/main/tutorial.scss b/dev/scss/main/tutorial.scss
index 3aeebb3..8f8d0f4 100644
--- a/dev/scss/main/tutorial.scss
+++ b/dev/scss/main/tutorial.scss
@@ -69,6 +69,32 @@
margin-left: $logo-left-distance + 15px;
}
+dl {
+ margin: 0;
+ padding-bottom: 2em;
+ dt {
+ font-weight: bold;
+ abbr {
+ border-width: 0;
+ &[data-type=token]::after {
+ color: $ids-blue-1;
+ }
+ &[data-type=span]::after {
+ color: $ids-pink-1;
+ }
+ &::after {
+ content: ' (' attr(title) ')';
+ vertical-align: bottom;
+ font-style: italic;
+ font-weight: normal;
+ font-size: 80%;
+ }
+ }
+ }
+}
+
+
+
/*
#tutorial {
iframe {
diff --git a/kalamar.conf b/kalamar.conf
index b062064..92c2c5b 100644
--- a/kalamar.conf
+++ b/kalamar.conf
@@ -49,12 +49,13 @@
go => 'Suche!',
in => 'in',
with => 'mit',
- glimpse => 'Stichproben',
+ glimpse => 'Stichprobe',
faq => 'Häufige Fragen',
tutorial => 'Einführung',
korap => {
-short => 'KorAP',
- long => 'KorAP - Korpusanalyseplattform der nächsten Generation'
+ long => 'KorAP - Korpusanalyseplattform der nächsten Generation',
+ overview => 'KorAP - Übersicht'
}
},
en => {
@@ -64,12 +65,13 @@
searchplaceholder => 'Find ...',
in => 'in',
with => 'with',
- glimpse => 'Glimpse',
+ glimpse => 'Sample',
faq => 'F.A.Q.',
tutorial => 'Tutorial',
korap => {
-short => 'KorAP',
- long => 'KorAP - Corpus Analysis Platform'
+ long => 'KorAP - Corpus Analysis Platform',
+ overview => 'KorAP - Overview'
}
}
}
diff --git a/lib/Kalamar/Controller/Documentation.pm b/lib/Kalamar/Controller/Documentation.pm
index 31d11cf..ef3b751 100644
--- a/lib/Kalamar/Controller/Documentation.pm
+++ b/lib/Kalamar/Controller/Documentation.pm
@@ -8,6 +8,8 @@
$c->stash(embedded => 1);
};
+ $c->stash(doc_base => 'http://localhost:3000/');
+
my @path = ('doc');
# There is a scope defined
diff --git a/lib/Kalamar/Plugin/KalamarTagHelpers.pm b/lib/Kalamar/Plugin/KalamarTagHelpers.pm
index 44d103e..7a51d7b 100644
--- a/lib/Kalamar/Plugin/KalamarTagHelpers.pm
+++ b/lib/Kalamar/Plugin/KalamarTagHelpers.pm
@@ -8,6 +8,24 @@
sub register {
my ($plugin, $mojo) = @_;
+
+ $mojo->helper(
+ korap_overview => sub {
+ my $c = shift;
+ my $scope = shift;
+ my $base = $c->stash('doc_base') ? '?' . $c->stash('doc_base') : '';
+
+ return $c->tag('object',
+ data => $c->url_for('/img/korap-overview.svg' . $base . '#' . $scope),
+ type => 'image/svg+xml',
+ alt => $c->loc('korap_overview'),
+ id => 'overview'
+ );
+ }
+ );
+
+
+
# Create helper for queries in the tutorial
$mojo->helper(
kalamar_tut_query => sub {
@@ -138,6 +156,22 @@
}
);
+ $mojo->helper(
+ doc_link_to => sub {
+ my $c = shift;
+ my $title = shift;
+ my $page = pop;
+ my $scope = shift;
+ return $c->link_to($title, $c->url_with('doc', scope => $scope, page => $page));
+ }
+ );
+
+ $mojo->helper(
+ doc_uc => sub {
+ return shift->tag('p', 'Under Construction!')
+ }
+ );
+
# Create links in the tutorial that make sure the current position is preserved,
# in case the tutorial was opened embedded
diff --git a/templates/doc/_nav.html.ep b/templates/doc/_nav.html.ep
new file mode 100644
index 0000000..8f9526f
--- /dev/null
+++ b/templates/doc/_nav.html.ep
@@ -0,0 +1,67 @@
+% content_for sidebar => begin
+<nav>
+ <ul>
+ <li><a href="/doc/korap" class="active">KorAP</a>
+ <ul>
+% foreach (qw/kalamar kustvakt koral krill karang/) {
+% my $url = url_with('doc', scope => '', page => $_);
+% $url->path->canonicalize;
+ <li><%= link_to ucfirst($_), $url %></li>
+% }
+ </ul>
+ </li>
+ <li><a href="/doc/ql">Query Languages</a>
+ <ul>
+% foreach ('Cosmas II'qw//) {
+% my $url = url_with('doc', scope => '', page => $_);
+% $url->path->canonicalize;
+ <li><%= link_to ucfirst($_), $url %></li>
+% }
+<!--
+ <li><a href="/doc/ql/cosmas-2">Cosmas II</a></li>
+ <li><a href="/doc/ql/poliqarp-plus">Poliqarp+</a>
+ <ul>
+ <li><a href="#tut-segments">Simple Segments</a></li>
+ <li><a href="#tut-complex">Complex Segments</a></li>
+ <li><a href="#tut-spans">Span Segments</a></li>
+ <li><a href="#tut-paradigmatic-operators">Paradigmatic Operators</a></li>
+ <li><a href="#tut-syntagmatic-operators">Syntagmatic Operators</a></li>
+ <li><a href="#tut-class-operators">Class Operators</a></li>
+ </ul>
+ </li>
+ <li><a href="/doc/ql/annis">Annis QL</a></li>
+ <li><a href="/doc/ql/cql">CQL</a></li>
+ <li><a href="/doc/ql/regexp">RegExp</a></li>
+->
+ </ul>
+ </li>
+ <li><a href="/doc/data">Data</a>
+ <ul>
+ <li><a href="/doc/data/corpus">Corpora</a>
+ <ul>
+ <li><a href="/doc/data/corpus/dereko">DeReKo</a></li>
+ </ul>
+ </li>
+ <li><a href="/doc/data/annotation">Annotations</a>
+ <ul>
+ <li><a href="/doc/data/annotation/connexor">Connexor</a></li>
+ <li><a href="/doc/data/annotation/mate">Mate</a></li>
+ <li><a href="/doc/data/annotation/treetagger">TreeTagger</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><a href="/doc/api">API</a>
+ <!--
+ <ul>
+ <li><a href="/doc/api/koralquery">KoralQuery</a></li>
+ <li><a href="/doc/api/search">Search API</a></li>
+ <li><a href="/doc/api/match">Match Information API</a></li>
+ <li><a href="/doc/api/user">User API</a></li>
+ </ul>
+ -->
+ </li>
+ <li><a href="/doc/faq">FAQ (mit Mail)</a>
+ </ul>
+</nav>
+% end
diff --git a/templates/doc/_nav.json b/templates/doc/_nav.json
new file mode 100644
index 0000000..931fa7f
--- /dev/null
+++ b/templates/doc/_nav.json
@@ -0,0 +1,167 @@
+[
+ {
+ "title": "KorAP",
+ "id" : "korap",
+ "items" : [
+ {
+ "title" : "Kalamar",
+ "id" : "kalamar"
+ },
+ {
+ "title" : "Kustvakt",
+ "id" : "kustvakt"
+ },
+ {
+ "title" : "Koral",
+ "id" : "koral"
+ },
+ {
+ "title" : "Krill",
+ "id" : "krill"
+ },
+ {
+ "title" : "Karang",
+ "id" : "karang"
+ }
+ ]
+ },
+ {
+ "title" : "Query Languages",
+ "id" : "ql",
+ "items" : [
+ {
+ "title" : "Cosmas II",
+ "id" : "cosmas-2"
+ },
+ {
+ "title" : "Poliqarp+",
+ "id" : "poliqarp-plus",
+ "class" : "folded",
+ "items" : [
+ {
+ "title" : "Simple Segments",
+ "id" : "#segments"
+ },
+ {
+ "title" : "Complex Segments",
+ "id" : "#complex"
+ },
+ {
+ "title" : "Span Segments",
+ "id" : "#spans"
+ },
+ {
+ "title" : "Paradigmatic Operators",
+ "id" : "#paradigmatic-operators"
+ },
+ {
+ "title" : "Syntagmatic Operators",
+ "id" : "#syntagmatic-operators"
+ },
+ {
+ "title" : "Class Operators",
+ "id" : "#class-operators"
+ }
+ ]
+ },
+ {
+ "title" : "Annis QL",
+ "id" : "annis"
+ },
+ {
+ "title" : "CQL",
+ "id" : "cql"
+ },
+ {
+ "title" : "Regular Expressions",
+ "id" : "regexp"
+ },
+ {
+ "title" : "Wildcards",
+ "id" : "wildcards"
+ }
+ ]
+ },
+ {
+ "title" : "Data",
+ "id" : "data",
+ "items" : [
+ {
+ "title" : "Corpora",
+ "id" : "corpus",
+ "class" : "folded",
+ "items" : [
+ {
+ "title" : "DeReKo",
+ "id" : "#dereko"
+ }
+ ]
+ },
+ {
+ "title" : "Annotations",
+ "id" : "annotation",
+ "class" : "folded",
+ "items" : [
+ {
+ "title" : "Base",
+ "id" : "#base"
+ },
+ {
+ "title" : "Connexor",
+ "id" : "#cnx"
+ },
+ {
+ "title" : "CoreNLP",
+ "id" : "#corenlp"
+ },
+ {
+ "title" : "TreeTagger",
+ "id" : "#tt"
+ },
+ {
+ "title" : "Mate",
+ "id" : "#mate"
+ },
+ {
+ "title" : "OpenNLP",
+ "id" : "#opennlp"
+ },
+ {
+ "title" : "XIP",
+ "id" : "#xip"
+ },
+ {
+ "title" : "Default Foundries",
+ "id" : "#default-foundries"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "title" : "API",
+ "id" : "api",
+ "items" : [
+ {
+ "title" : "KoralQuery",
+ "id" : "koralquery"
+ },
+ {
+ "title" : "Search API",
+ "id" : "search"
+ },
+ {
+ "title" : "Match API",
+ "id" : "match"
+ },
+ {
+ "title" : "User API",
+ "id" : "user"
+ }
+ ]
+ },
+ {
+ "title" : "F.A.Q.",
+ "id" : "faq"
+ }
+]
diff --git a/templates/doc/api.html.ep b/templates/doc/api.html.ep
new file mode 100644
index 0000000..ea9c594
--- /dev/null
+++ b/templates/doc/api.html.ep
@@ -0,0 +1,16 @@
+% layout 'main', title => 'KorAP: Application Programming Interface';
+
+<h2>Application Programming Interface</h2>
+
+<p>Internally the communication between the KorAP components is done using the <%= doc_link_to('KoralQuery', 'api', 'koralquery') %> protocol. The following endpoints make use of this protocol or establish additional mechanisms. All described endpoints are (more or lest) REST-ful web APIs.</p>
+
+<dl>
+ <dt><%= doc_link_to('Search API', 'api', 'search') %></dt>
+ <dd>Initiate queries, create virtual collections.</dd>
+
+ <dt><%= doc_link_to('Match API', 'api', 'match') %></dt>
+ <dd>Retrieve further information like annotations for a certain match.</dd>
+
+ <dt><%= doc_link_to('User API', 'api', 'user') %></dt>
+ <dd>Log in, log out, and set and retrieve user properties.</dd>
+</dl>
diff --git a/templates/doc/api/koralquery.html.ep b/templates/doc/api/koralquery.html.ep
new file mode 100644
index 0000000..4795573
--- /dev/null
+++ b/templates/doc/api/koralquery.html.ep
@@ -0,0 +1,7 @@
+% layout 'main', title => 'KorAP: KoralQuery';
+
+<h2>KoralQuery</h2>
+
+<p><strong>Main developer:</strong> Nils Diewald, Joachim Bingel</p>
+
+<p>The specification for KoralQuery is available on <a href="http://korap.github.io/Koral">GitHub</a>.</p>
diff --git a/templates/doc/api/match.html.ep b/templates/doc/api/match.html.ep
new file mode 100644
index 0000000..5de2210
--- /dev/null
+++ b/templates/doc/api/match.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Match API';
+
+<h2>Match API</h2>
+
+%= doc_uc
diff --git a/templates/doc/api/search.html.ep b/templates/doc/api/search.html.ep
new file mode 100644
index 0000000..5fc864d
--- /dev/null
+++ b/templates/doc/api/search.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Search API';
+
+<h2>Search API</h2>
+
+%= doc_uc
diff --git a/templates/doc/api/user.html.ep b/templates/doc/api/user.html.ep
new file mode 100644
index 0000000..12fa82e
--- /dev/null
+++ b/templates/doc/api/user.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: User API';
+
+<h2>User API</h2>
+
+%= doc_uc
diff --git a/templates/doc/data.html.ep b/templates/doc/data.html.ep
new file mode 100644
index 0000000..1892a3a
--- /dev/null
+++ b/templates/doc/data.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Data';
+
+<h2>Data</h2>
+
+<p>Under Construction</p>
diff --git a/templates/doc/data/annotation.html.ep b/templates/doc/data/annotation.html.ep
new file mode 100644
index 0000000..803d059
--- /dev/null
+++ b/templates/doc/data/annotation.html.ep
@@ -0,0 +1,108 @@
+% layout 'main', title => 'KorAP: Annotations';
+
+<h2>Annotations</h2>
+
+<p>KorAP provides access to multiple levels of annotations originating from multiple resources, so called <em>foundries</em>.</p>
+
+<section id="base">
+ <h3>Base Foundry</h3>
+ <p>The base foundry is available for all corpora and acts as a common ground for document structure annotation. It supports two types of spans: <code><s></code> for sentences and <code><p></code> for paragraphs - this will likely change in the next index version. These spans lack prefix information!</p>
+ %= kalamar_tut_query poliqarp => '<s>', cutoff => 1
+</section>
+
+
+<section id="cnx">
+ <h3>Connexor (<code>cnx</code>)</h3>
+ <p>Connexor annotations provide the following layer for the <code>cnx</code> prefix:</p>
+ <dl>
+ <dt><abbr data-type="token" title="Lemma">l</abbr></dt>
+ <dd>All lemmas are written in lower case. Composita are split, e.g. the token "Leitfähigkeit" is matched by the lemmas "leit" and "fähigkeit" - not by the lemma "leitfähigkeit"</dd>
+ <dt><abbr data-type="token" title="Part-of-Speech">p</abbr></dt>
+ <dd>Part-of-speech information is written in capital letters and is based on STTS</dd>
+ <dt><abbr data-type="token" title="Syntactical information">syn</abbr></dt>
+ <dd>Includes token based information like <code>@PREMOD</code>, <code>@NH</code>, <code>@MAIN</code> ...</dd>
+ <dt><abbr data-type="token" title="Morphosyntactical information">m</abbr></dt>
+ <dd>Includes information about tense (<code>PRES</code> ...), mode (<code>IND</code>), number (<code>PL</code> ...) etc.</dd>
+ <dt><abbr data-type="span" title="Phrases">c</abbr></dt>
+ <dd>Only nominal phrases are available and all nominal phrases are written in lower case (<code>np</code>)</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[cnx/p=CC]', cutoff => 1
+</section>
+
+
+<section id="corenlp">
+ <h3>CoreNLP (<code>corenlp</code>)</h3>
+ <dl>
+ <dt><abbr data-type="token" title="Named Entity">ne_hgc_175m_600</abbr></dt>
+ <dd>Contains named entities like <code>I-PER</code>, <code>I-ORG</code> etc.</dd>
+ <dt><abbr data-type="token" title="Named Entity">ne_dewac_175_175m_600</abbr></dt>
+ <dd>See above</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[corenlp/ne_dewac_175m_600=I-ORG]', cutoff => 1
+</section>
+
+
+<section id="tt">
+ <h3>TreeTagger (<code>tt</code>)</h3>
+ <dl>
+ <dt><abbr data-type="token" title="Lemma">l</abbr></dt>
+ <dd>All non-noun lemmas are written in lower case, nouns are written upper case. Composita stay intact (e.g. <code>Normalbedingung</code>)</dd>
+ <dt><abbr data-type="token" title="Part-of-Speech">p</abbr></dt>
+ <dd>All part-of-speech information is written in capital letters and is based on STTS</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[tt/p=ADV]', cutoff => 1
+</section>
+
+
+<section>
+ <h3>Mate (<code>mate</code>)</h3>
+ <dl>
+ <dt><abbr data-type="token" title="Lemma">l</abbr></dt>
+ <dd>All lemmas are written in lower case. Composita stay intact (e.g. <code>buchstabenbezeichnung</code>)</dd>
+ <dt><abbr data-type="token" title="Part-of-Speech">p</abbr></dt>
+ <dd>All part-of-speech information is written in capital letters and is based on STTS</dd>
+ <dt><abbr data-type="token" title="Morphosyntactical information">m</abbr></dt>
+ <dd>Includes information about tense (<code>tense:pres</code> ...), mode (<code>mood:ind</code>), number (<code>number:pl</code> ...), gender (<code>gender:masc</code> ...) etc.</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[mate/m=gender:fem]', cutoff => 1
+</section>
+
+
+<section id="opennlp">
+ <h3>OpenNLP (<code>opennlp</code>)</h3>
+ <dl>
+ <dt><abbr data-type="token" title="Part-of-Speech">p</abbr></dt>
+ <dd>All part-of-speech information is written in capital letters and is based on STTS</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[opennlp/p=PDAT]', cutoff => 1
+</section>
+
+
+<section id="xip">
+ <h3>Xerox Incremental Parser (<code>xip</code>)</h3>
+ <dl>
+ <dt><abbr data-type="token" title="Lemma">l</abbr></dt>
+ <dd>All non-noun lemmas are written in lower case, nouns are written upper case. Composita are split, e.g. the token <code>Leitfähigkeit</code> is matched by the lemmas <code>leiten</code> and <code>Fähigkeit</code> - and by a merged and pretty useless <code>leitenfähigkeit</code> (This is going to change)</dd>
+ <dt><abbr data-type="token" title="Part-of-Speech">p</abbr></dt>
+ <dd>All part-of-spech information is written in capital letters and is based on STTS</dd>
+ <dt><abbr data-type="span" title="Phrases">c</abbr></dt>
+ <dd>Some phrases to create sentences, all upper case (<code>NP</code>, <code>NPA</code>, <code>NOUN</code>, <code>VERB</code>, <code>PREP</code>, <code>AP</code> ...)</dd>
+ </dl>
+ %= kalamar_tut_query poliqarp => '[xip/p=ADJ]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '<xip/c=VERB>', cutoff => 1
+</section>
+
+<section id="default-foundries">
+ <h3>Default Foundries</h3>
+ <p>For queries on specific layers without given foundries, KorAP provides default foundries, that can be overwritten by user configurations. The default foundries apply to the following layers:</p>
+
+ <ul>
+ <li><strong>orth</strong>: <code>opennlp</code></li>
+ <li><strong>lemma</strong>: <code>tt</code></li>
+ <li><strong>pos</strong>: <code>tt</code></li>
+ </ul>
+
+ <blockquote>
+ <p>In the Lucene backend, the <code>orth</code> layer can only be bound to a specific foundry, as only one tokenization is supported.</p>
+ </blockquote>
+</section>
diff --git a/templates/doc/faq.html.ep b/templates/doc/faq.html.ep
new file mode 100644
index 0000000..10f7e01
--- /dev/null
+++ b/templates/doc/faq.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: F.A.Q.';
+
+<h2>Frequently Asked Questions</h2>
+
+%= doc_uc
diff --git a/templates/doc/korap.html.ep b/templates/doc/korap.html.ep
new file mode 100644
index 0000000..08eb9a7
--- /dev/null
+++ b/templates/doc/korap.html.ep
@@ -0,0 +1,66 @@
+% layout 'main', title => 'KorAP: Overview';
+
+<h2>KorAP: An Overview</h2>
+
+%= korap_overview 'korap'
+
+<p>The KorAP project was launched in 2011 at the <a href="http://www.ids-mannheim.de/">Institute for the German Language (IDS)</a> in Mannheim, Germany. KorAP is a Corpus Analysis Platform, with an extensible and scalable architecture. It consists of multiple components, that are exchangable due to well defined APIs.</p>
+
+<dl>
+ <dt><%= doc_link_to('Kalamar', 'korap', 'kalamar') %></dt>
+ <dd>Kalamar is the user frontend. Most users will access the search and analysis capabilities of KorAP through the user frontend. The user will formulate queries in one of several query languages that are passed to Kustvakt.</dd>
+
+ <dt><%= doc_link_to('API', 'api') %></dt>
+ <dd>As an alternative to the user frontend, queries can be initiated using a REST web interface directly with Kustvakt.</dd>
+
+ <dt><%= doc_link_to('Kustvakt', 'korap', 'kustvakt') %></dt>
+ <dd>Kustvakt is the central user and policy management service. It takes a query and rewrites it to restrict the scope of a search to documents the user is allowed to. It may also inject further properties the user has set up, like preferred annotation layers. To transfer a query written in a certain query language to the internal general query protocol <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>, Kustvakt uses <%= doc_link_to('Koral', 'korap', 'koral') %>.</dd>
+
+ <dt><%= doc_link_to('Kustvakt', 'korap', 'kustvakt') %></dt>
+ <dd>Kustvakt is the central user and policy management service. It takes a query and rewrites it to restrict the scope of a search to documents the user is allowed to. It may also inject further properties the user has set up, like preferred annotation layers. To transfer a query written in a certain query language to the internal general query protocol <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>, Kustvakt uses <%= doc_link_to('Koral', 'korap', 'koral') %>.</dd>
+
+ <dt><%= doc_link_to('Koral', 'korap', 'koral') %></dt>
+ <dd>Koral is a library that translates queries written in one of several implemented query languages into a general query protocol, called <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>.</dd>
+
+ <dt><%= doc_link_to('Krill', 'korap', 'krill') %></dt>
+ <dd>Krill is a Lucene based backend engine that can search large corpora for occurrences of search patterns formulated in <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>.</dd>
+
+ <dt><%= doc_link_to('Karang', 'korap', 'karang') %></dt>
+ <dd>Karang is a Neo4j based backend engine that can traverse large corpora represented as graphs.</dd>
+</dl>
+
+<h3>Team</h3>
+
+<dl>
+ <dt>Head</dt>
+ <dd>
+ <a href="http://www.ids-mannheim.de/direktion/personal/kupietz.html">Dr. Marc Kupietz</a>,
+ <a href="http://www.ids-mannheim.de/direktion/personal/witt.html">Dr. Andreas Witt</a>
+ </dd>
+
+ <dt>Scientific Staff</dt>
+ <dd>
+ <a href="http://www.ids-mannheim.de/direktion/personal/banski.html">Dr. Piotr Bański</a> (Coordination),
+ <a href="http://nils-diewald.de/">Nils Diewald</a>,
+ <a href="http://www.ids-mannheim.de/direktion/personal/frick/">Elena Frick</a>,
+ Michael Hanl
+ </dd>
+
+ <dt>Extended project crew</dt>
+ <dd>
+ <a href="http://www.ids-mannheim.de/direktion/personal/bingel.html">Joachim Bingel</a>,
+ <a href="http://www.ids-mannheim.de/direktion/personal/margaretha/">Eliza Margaretha</a>,
+ <a href="http://www.ids-mannheim.de/zdv/personal/bodmer.html">Franck Bodmer</a>,
+ <a href="http://www.ids-mannheim.de/zdv/personal/harders.html">Peter Harders</a>,
+ <a href="http://www.ids-mannheim.de/zdv/personal/krause.html">Helge Stallkamp</a>
+ </dd>
+
+ <dt>Past Project Members</dt>
+ <dd><a href="http://www.ids-mannheim.de/direktion/personal/ehemalige/schnober.html">Carsten Schnober</a></dd>
+
+ <dt>Consulting</dt>
+ <dd>
+ <a href="http://www.ids-mannheim.de/direktion/personal/belica.html">Cyril Belica</a>,
+ <a href="http://www.ids-mannheim.de/direktion/personal/schonefeld/">Oliver Schonefeld</a>
+ </dd>
+</dl>
diff --git a/templates/doc/korap/kalamar.html.ep b/templates/doc/korap/kalamar.html.ep
new file mode 100644
index 0000000..8422747
--- /dev/null
+++ b/templates/doc/korap/kalamar.html.ep
@@ -0,0 +1,9 @@
+% layout 'main', title => 'KorAP: Kalamar';
+
+<h2>Kalamar</h2>
+
+%= korap_overview 'kalamar'
+
+<p><strong>Main developer:</strong> Nils Diewald</p>
+
+<p>Kalamar is the main user frontend of KorAP. It is based on <a href="http://mojolicio.us/">Mojolicious</a> and written in Perl and JavaScript.</p>
diff --git a/templates/doc/korap/karang.html.ep b/templates/doc/korap/karang.html.ep
new file mode 100644
index 0000000..67772a6
--- /dev/null
+++ b/templates/doc/korap/karang.html.ep
@@ -0,0 +1,9 @@
+% layout 'main', title => 'KorAP: Karang';
+
+<h2>Karang</h2>
+
+%= korap_overview 'karang'
+
+<p><strong>Main developer:</strong> Piotr Pęzik</p>
+
+<p>Karang is a Neo4j based search backend for KorAP.</p>
diff --git a/templates/doc/korap/koral.html.ep b/templates/doc/korap/koral.html.ep
new file mode 100644
index 0000000..273df7d
--- /dev/null
+++ b/templates/doc/korap/koral.html.ep
@@ -0,0 +1,11 @@
+% layout 'main', title => 'KorAP: Koral';
+
+<h2>Koral</h2>
+
+%= korap_overview 'koral'
+
+<p><strong>Main developer:</strong> Joachim Bingel</p>
+
+<p>Koral is a library designed for the translation of different corpus query languages to <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>. Currently supported query languages include <%= doc_link_to 'Cosmas II', 'ql', 'cosmas2' %>, <%= doc_link_to('Annis QL', 'ql', 'annis') %>, <%= doc_link_to('Poliqarp+', 'ql', 'poliqarp-plus') %> (an extended version of Poliqarp) and <%= doc_link_to('CQL', 'ql', 'cql') %>.</p>
+
+<p>Koral is open source and available on <a href="https://github.com/KorAP/Koral">GitHub</a>.</p>
diff --git a/templates/doc/korap/krill.html.ep b/templates/doc/korap/krill.html.ep
new file mode 100644
index 0000000..cb013c0
--- /dev/null
+++ b/templates/doc/korap/krill.html.ep
@@ -0,0 +1,11 @@
+% layout 'main', title => 'KorAP: Krill';
+
+<h2>Krill</h2>
+
+%= korap_overview 'krill'
+
+<p><strong>Main developer:</strong> Nils Diewald, Eliza Margaretha</p>
+
+<p>Krill is a <a href="https://lucene.apache.org/">Lucene</a> based search engine for large annotated corpora, used as a backend component for KorAP. It is the reference implementation for <%= doc_link_to('KoralQuery', 'api', 'koralquery') %>, covering most of the protocols features.</p>
+
+<p>Krill is open source and available on <a href="https://github.com/KorAP/Krill">GitHub</a>.</p>
diff --git a/templates/doc/korap/kustvakt.html.ep b/templates/doc/korap/kustvakt.html.ep
new file mode 100644
index 0000000..5b084ae
--- /dev/null
+++ b/templates/doc/korap/kustvakt.html.ep
@@ -0,0 +1,9 @@
+% layout 'main', title => 'KorAP: Kustvakt';
+
+<h2>Kustvakt</h2>
+
+%= korap_overview 'kustvakt'
+
+<p><strong>Main developer:</strong> Michael Hanl</p>
+
+<p>Kustvakt is a user and policy management software, that is capable of rewriting queries for policy based document restrictions.</p>
diff --git a/templates/doc/ql.html.ep b/templates/doc/ql.html.ep
new file mode 100644
index 0000000..37240c0
--- /dev/null
+++ b/templates/doc/ql.html.ep
@@ -0,0 +1,53 @@
+% layout 'main', title => 'KorAP: Query Languages';
+
+%# https://letsencrypt.org/howitworks/
+
+%# Store the id of an active section in the session, so the system is able to directly scroll to the relevant section
+%# This should be stored when clicking on a specific query
+%# but the remembered section contains the id - not the query
+
+<h2>Query Languages</h2>
+
+<section id="tut-intro">
+ <h3>Frontend Features</h3>
+ <p>This frontend differs to the <%= link_to 'official frontend', 'http://korap.ids-mannheim.de/app/', target => '_blank' %> by providing a serialization view, an integrated tutorial, a comparison view for morphological annotations, and an autocompletion for closed annotations (type in <%= kalamar_tut_link_to 'foundry prefixes', '/tutorial/foundries' %> like <code>cnx/</code>).</p>
+</section>
+
+<section id="tut-examples">
+ <h3>Example Queries</h3>
+
+ %# Tests:
+ %# [is => 'json_pointer', 'result']
+ %# [ok => 'json_pointer']
+ %# [isnt => 'json_pointer', 'result']
+ %# [not_ok => 'json_pointer']
+
+ <p><strong>Poliqarp</strong>: Find all occurrences of the lemma "baum" as annotated by the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>.</p>
+ %= kalamar_tut_query poliqarp => '[base=Baum]', 'tests' => [[is => '/query', 'tokens:tt/l:Baum'],[is => '/request/query/wrap/layer', 'lemma'],[is => '/request/query/wrap/foundry', 'tt'], [ok => '/matches/10']]
+
+ <p><strong>Poliqarp</strong>: Find all sequences of adjectives as annotated by Treetagger, that are repeated 3 to 5 times in a row.</p>
+ %= kalamar_tut_query poliqarp => '[tt/p=ADJA]{3,5}', 'tests' => [[is => '/query', 'spanRepetition(tokens:tt/p:ADJA{3,5})'], [is => '/request/query/operation', 'operation:repetition'],[is => '/request/query/operands/0/wrap/foundry', 'tt'], [ok => '/matches/5']]
+
+ <p><strong>Cosmas-II</strong>: Find all occurrences of the words "der" and "Baum", in case they are in a maximum distance of 5 tokens. The order is not relevant.</p>
+ %= kalamar_tut_query cosmas2 => 'der /w5 Baum', 'tests' => [[is => '/query', 'shrink(129: spanDistance({129: tokens:s:der}, {129: tokens:s:Baum}, [(w[0:5], notOrdered, notExcluded)]))'], [is => '/request/query/operation', 'operation:focus'], [is => '/request/query/@type', 'korap:reference'],[is => '/request/query/operands/0/operands/1/operation', 'operation:class'], [is => '/itemsPerPage', 25], [ok => '/matches/20'], [is => '/matches/4/corpusID', 'WPD'], [is => '/matches/12/corpusID', 'WPD']]
+
+ <p><strong>Cosmas-II</strong>: Find all sequences of a word starting with a "d" (using a wildcard) followed by an adjective as annotated in the mate foundry, followed by the word "Baum" (ignore the case), that is in a sentence element annotated by the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>.</p>
+ <p><em>Be aware</em>: Minor incompatibilities with implemented languages may be announced with warnings.</p>
+ %= kalamar_tut_query cosmas2 => 'd* MORPH(mate/p=ADJA) $Baum #IN #ELEM(s)', 'tests' => [[ok => '/matches/3'], [is => '/query', 'shrink(130: {131: spanContain({129: <tokens:s />}, {130: spanNext(spanNext(SpanMultiTermQueryWrapper(tokens:s:d*), tokens:mate/p:ADJA), tokens:i:baum)})})'], [is => '/request/query/@type', 'korap:reference'], [is => '/request/query/operation', 'operation:focus'], [is => '/request/query/operands/0/operands/0/operation', 'operation:position'], [is => '/request/query/operands/0/operands/0/operands/1/operands/0/operation', 'operation:sequence'], [is => '/request/query/operands/0/operands/0/operands/1/operands/0/operands/0/wrap/type', 'type:wildcard'], [is => '/request/query/operands/0/operands/0/operands/1/operands/0/operands/1/wrap/key', 'ADJA'], [is => '/request/query/operands/0/operands/0/operands/1/operands/0/operands/1/wrap/foundry', 'mate'], [ok => '/request/query/operands/0/operands/0/operands/1/operands/0/operands/2/wrap/caseInsensitive'], [ok => '/matches/5']]
+
+ <p><strong>Poliqarp+</strong>: Find all nominal phrases as annotated using Connexor, that contain an adverb as annotated by OpenNLP, that is annotated as something starting with an "A" using regular expressions in Treetagger.</p>
+ %= kalamar_tut_query poliqarp => 'contains(<cnx/c=np>,{[opennlp/p=ADV & tt/p="A.*"]})', cutoff => 1, 'tests' => [[is => '/query', 'spanContain(<tokens:cnx/c:np />, {1: spanSegment(tokens:opennlp/p:ADV, SpanMultiTermQueryWrapper(tokens:/tt/p:A.*/))})'], [is => '/request/query/operation', 'operation:position'], [is => '/request/query/frames/0', 'frames:contains'], [is => '/request/query/operands/0/foundry', 'cnx'], [is => '/request/query/operands/0/layer', 'c'], [is => '/request/query/operands/0/foundry', 'cnx'], [is => '/request/query/operands/0/key', 'np'], [is => '/request/query/operands/1/operands/0/wrap/operands/0/foundry', 'opennlp'], [is => '/request/query/operands/1/operands/0/wrap/operands/0/layer', 'p'], [is => '/request/query/operands/1/operands/0/wrap/operands/1/foundry', 'tt'], [is => '/request/query/operands/1/operands/0/wrap/operands/1/type', 'type:regex'], [is => '/request/query/operands/1/operands/0/wrap/operands/1/key', 'A.*'], [ok => '/matches/5']]
+
+ <p><strong>Poliqarp+</strong>: Find all sentences as annotated by the base foundry that start with a sequence of one token in present tense as annotated by Connexor and the lemma "die" annotated by the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>. Highlight both terms of the sequence.</p>
+ %= kalamar_tut_query poliqarp => 'startswith(<s>, {1:[cnx/m=PRES]}{2:[base=die]})', cutoff => 1, tests => [[is => '/query', 'spanStartsWith(<tokens:s />, spanNext({1: tokens:cnx/m:PRES}, {2: tokens:tt/l:die}))'], [is => '/request/meta/startPage', 1], [is => '/request/query/operation', 'operation:position'], [is => '/request/query/operands/0/@type','korap:span'], [is => '/request/query/operands/1/operands/0/operation', 'operation:class'], [is => '/request/query/operands/1/operands/1/operation', 'operation:class'], [is => '/request/query/operands/1/operands/1/operands/0/wrap/foundry', 'tt'], [ok => '/matches/4']]
+
+ <p><strong>Poliqarp+</strong>: Find all sequences of an article, followed by three to four adjectives and a noun as annotated by the Treetagger foundry, that finish a sentence. Highlight all parts of the sequence.</p>
+ %= kalamar_tut_query poliqarp => 'focus(3:endswith(<s>,{3:[tt/p=ART]{1:{2:[tt/p=ADJA]{3,4}}[tt/p=NN]}}))', cutoff => 1, 'tests' => [[is => '/query', 'shrink(3: spanEndsWith(<tokens:s />, {3: spanNext(tokens:tt/p:ART, {1: spanNext({2: spanRepetition(tokens:tt/p:ADJA{3,4})}, tokens:tt/p:NN)})}))'], [is => '/request/query/operation', 'operation:focus'], [is => '/request/query/operands/0/frames/0', 'frames:endswith'], [ok => '/matches/3'], [is => '/matches/4/corpusID', 'WPD']]
+
+ <p><strong>Annis</strong>: Find all occurrences of the sequence of two tokens annotated as adverbs by the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>.</p>
+ %= kalamar_tut_query annis => 'pos="ADV" & pos="ADV" & #1 . #2', 'tests' => [[is => '/query', 'spanNext(tokens:tt/p:ADV, tokens:tt/p:ADV)'], [is => '/request/query/operands/0/wrap/foundry', 'tt'], [is => '/request/query/operands/1/wrap/foundry', 'tt'], [ok => '/matches/5'], [ok => '/matches/15'], [is => '/matches/15/corpusID', 'WPD']]
+
+ <p><strong>CQL</strong>: Find all occurrences of the sequence "der alte Mann".</p>
+ %= kalamar_tut_query cql => '"der alte Mann"', 'tests' => [[is => '/query', 'spanNext(spanNext(tokens:s:der, tokens:s:alte), tokens:s:Mann)'], [is => '/request/query/operation', 'operation:sequence'],[is => '/request/query/operands/0/wrap/key', 'der'],[is => '/request/query/operands/1/wrap/key', 'alte'],[is => '/request/query/operands/2/wrap/key', 'Mann'], [ok => '/matches/5'], [ok => '/matches/5']]
+
+</section>
diff --git a/templates/doc/ql/annis.html.ep b/templates/doc/ql/annis.html.ep
new file mode 100644
index 0000000..f0198ef
--- /dev/null
+++ b/templates/doc/ql/annis.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Annis QL';
+
+<h2>Annis QL</h2>
+
+%= doc_uc
diff --git a/templates/doc/ql/cosmas-2.html.ep b/templates/doc/ql/cosmas-2.html.ep
new file mode 100644
index 0000000..7ec7135
--- /dev/null
+++ b/templates/doc/ql/cosmas-2.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Cosmas II';
+
+<h2>Cosmas II</h2>
+
+%= doc_uc
diff --git a/templates/doc/ql/poliqarp-plus.html.ep b/templates/doc/ql/poliqarp-plus.html.ep
new file mode 100644
index 0000000..7d0ede1
--- /dev/null
+++ b/templates/doc/ql/poliqarp-plus.html.ep
@@ -0,0 +1,319 @@
+% layout 'main', title => 'KorAP: Poliqarp+';
+
+<h2>Poliqarp+</h2>
+
+<p>The following tutorial introduces all features provided by our version of the Poliqarp Query Language and some KorAP specific extensions.</p>
+
+<section id="tut-segments">
+ <h3>Simple Segments</h3>
+
+ <p>The atomic elements of Poliqarp queries are segments. Most of the time segments represent words and can be simply queried:</p>
+ %# footnote: In the polish national corpus, Poliqarp can join multiple segments when identifying a single word.
+
+ %= kalamar_tut_query poliqarp => 'Baum'
+
+ <p>Sequences of simple segments are expressed using a space delimiter:</p>
+
+ %= kalamar_tut_query poliqarp => 'der Baum'
+
+ <p>Simple segments always refer to the surface form of a word. To search for surface forms without case sensitivity, you can use the <code>/i</code> flag.</p>
+
+ %= kalamar_tut_query poliqarp => 'laufen/i'
+
+ <p>The query above will find all occurrences of <code>laufen</code> irrespective of the capitalization of letters, so <code>wir laufen</code> will be find as well as <code>das Laufen</code> and even <code>"GEH LAUFEN!"</code>.
+
+ <h4 id="tut-regexp">Regular Expressions</h4>
+
+ <p>Segments can also be queried using <%= kalamar_tut_link_to 'regular expressions', '/tutorial/regular-expressions' %> - by surrounding the segment with double quotes.</p>
+
+ %= kalamar_tut_query poliqarp => '"l(au|ie)fen"'
+
+ <p>Regular expression segments will always match the whole segment, meaning the above query will find words starting with <code>l</code> and ending with <code>n</code>. To support subqueries, you can use the <code>/x</code> flag.
+
+ %= kalamar_tut_query poliqarp => '"l(au|ie)fen"/x', cutoff => 1
+
+ <p>The <code>/x</code> will search for all segments that contain a sequence of characters the regular expression matches. That means the above query is equivalent to:</p>
+
+ %= kalamar_tut_query poliqarp => '".*?l(au|ie)fen.*?"', cutoff => 1
+
+ <p>The <code>/x</code> flag can also be used in conjuntion with strict expressions to search for substrings:</p>
+
+ %= kalamar_tut_query poliqarp => 'trenn/xi', cutoff => 1
+
+ <p>The above query will find all occurrences of segments including the string <code>trenn</code> case insensitive, like "Trennung", "unzertrennlich", or "Wettrennen".</p>
+
+ <blockquote class="warning">
+ <p>Beware: These kinds of queries (with prepended <code>.*</code> expressions) are extremely slow!</p>
+ </blockquote>
+
+ <p>You can again apply the <code>/i</code> flag to search case insensitive.</p>
+
+ %= kalamar_tut_query poliqarp => '"l(au|ie)fen"/xi', cutoff => 1
+</section>
+
+<section id="tut-complex">
+ <h3>Complex Segments</h3>
+
+ <p>Complex segments are expressed in square brackets and contain additional information on the resource of the term under scrutiny by providing key/value pairs, separated by an equal-sign.</p>
+
+ <p>The KorAP implementation of Poliqarp provides three special segment keys: <code>orth</code> for surface forms, <code>base</code> for lemmata, and <code>pos</code> for Part-of-Speech. The following complex query finds all surface forms of <code>Baum</code>.</p>
+ %# There are more special keys in Poliqarp, but KorAP doesn't provide them.
+
+ %= kalamar_tut_query poliqarp => '[orth=Baum]'
+
+ <p>The query is thus equivalent to:</p>
+
+ %= kalamar_tut_query poliqarp => 'Baum'
+
+ <p>Complex segments expect simple expressions as values, meaning that the following expression is valid as well:</p>
+
+ %= kalamar_tut_query poliqarp => '[orth="l(au|ie)fen"/xi]', cutoff => 1
+
+ <p>Another special key is <code>base</code>, refering to the lemma annotation of the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>.
+ The following query finds all occurrences of segments annotated as the lemma <code>Baum</code> by the default foundry.</p>
+
+ %= kalamar_tut_query poliqarp => '[base=Baum]'
+
+ <p>The third special key is <code>pos</code>, refering to the part-of-speech annotation of the <%= kalamar_tut_link_to 'default foundry', '/tutorial/foundries' %>.
+ The following query finds all attributive adjectives:</p>
+
+ %= kalamar_tut_query poliqarp => '[pos=ADJA]'
+
+ <p>Complex segments requesting further token annotations can have keys following the <code>foundry/layer</code> notation.
+ For example to find all occurrences of plural words in the mate foundry, you can search using the following query:</p>
+
+ %= kalamar_tut_query poliqarp => '[mate/m=number:pl]'
+
+ <h4>Negation</h4>
+ <p>Negation of terms in complex expressions can be expressed by prepending the equal sign with an exclamation mark or by prepending the expression with one.</p>
+
+ %= kalamar_tut_query poliqarp => '[pos!=ADJA]'
+ %= kalamar_tut_query poliqarp => '[!pos=ADJA]'
+
+ <blockquote class="warning">
+ <p>Beware: Negated complex segments can't be searched solely in the Lucene index.
+ However, they work in case they are part of a <a href="#tut-syntagmatic-operators-sequence">sequence</a>.</p>
+ </blockquote>
+
+ <h4 id="empty-segments">Empty Segments</h4>
+
+ <p>A special segment is the empty segment, that matches every word in the index.</p>
+
+ %= kalamar_tut_query poliqarp => '[]'
+
+ <p>Empty segments are useful to express distances of words by using <a href="tut-syntagmatic-operators-repetitions">repetitions</a>.</p>
+
+ <blockquote class="warning">
+ <p>Beware: Empty segments can't be searched solely in the Lucene index.
+ However, they work in case they are part of a <a href="#tut-syntagmatic-operators-sequence">sequence</a>.</p>
+ </blockquote>
+</section>
+
+<section id="tut-spans">
+ <h3>Span Segments</h3>
+
+ <p>Not all segments are bound to words - some are bound to concepts spanning multiple words, for example noun phrases, sentences, or paragraphs.
+Span segments can be searched for using angular brackets instead of square brackets.</p>
+
+ %= kalamar_tut_query poliqarp => '<xip/c=INFC>'
+
+ <p>Otherwise they can be treated in exactly the same way as simple or complex segments.</p>
+</section>
+
+<section id="tut-paradigmatic-operators">
+ <h3>Paradigmatic Operators</h3>
+
+ <p>A complex segment can have multiple properties a token has to fulfill. For example to search for all words with the surface form <code>laufe</code> (no matter if capitalized or not) that have the lemma <code>lauf</code> (and not, for example, <code>laufen</code>, which would indicate a verb or a gerund), you can search for:</p>
+
+ %= kalamar_tut_query poliqarp => '[orth=laufe/i & base=Lauf]'
+
+ <p>The ampersand combines multiple properties with a logical AND.
+Terms of the complex segment can be negated as introduced before.</p>
+
+ %= kalamar_tut_query poliqarp => '[orth=laufe/i & base!=Lauf]'
+
+ <p>The following query is therefore equivalent:</p>
+
+ %= kalamar_tut_query poliqarp => '[orth=laufe & !base=Lauf]'
+
+ <p>Alternatives can be expressed by using the pipe symbol:</p>
+
+ %= kalamar_tut_query poliqarp => '[base=laufen | base=gehen]'
+
+ <p>All these sub expressions can be grouped using round brackets to form complex boolean expressions:</p>
+
+ %= kalamar_tut_query poliqarp => '[(base=laufen | base=gehen) & tt/pos=VVFIN]'
+</section>
+
+<section id="tut-syntagmatic-operators">
+ <h3>Syntagmatic Operators</h3>
+
+ <h4 id="tut-syntagmatic-operators-sequence">Sequences</h4>
+
+ <p>Sequences can be used to search for segments in order. For example to search for the word "alte" preceded by "der" and followed by "Mann", you can simple search for the sequence of simple expressions separated by whitespaces.</p>
+
+ %= kalamar_tut_query poliqarp => 'der alte Mann'
+
+ <p>However, you can obviously search using complex segments as well:</p>
+
+ %= kalamar_tut_query poliqarp => '[orth=der][orth=alte][orth=Mann]'
+
+ <p>Now you may see the benefit of the empty segment to search for words you don't know:</p>
+
+ %= kalamar_tut_query poliqarp => '[orth=der][][orth=Mann]'
+
+ <p>You are also able to mix segments and spans in sequences, for example to search for the word "Der" at the beginning of a sentence (which can be interpreted as the first word after the end of a sentence).</p>
+
+ %= kalamar_tut_query poliqarp => '<s>[orth=Der]'
+
+ <h4>Groups</h4>
+
+ ...
+
+ <h4>Alternation</h4>
+
+ <p>Alternations allow for searching alternative segments or sequences of segments, similar to the paradigmatic operator. You already have seen that you can search for both sequences of <code>der alte Mann</code> and <code>der junge Mann</code> by typing in:</p>
+
+ %= kalamar_tut_query poliqarp => 'der [orth=alte | orth=junge] Mann'
+
+ <p>However, this formulation has problems in case you want to search for alternations of sequences rather than terms. If you want to search for both sequences of <code>dem jungen Mann</code> and <code>der alte Mann</code> you can use syntagmatic alternations and groups:</p>
+
+ %= kalamar_tut_query poliqarp => '(dem jungen | der alte) Mann'
+
+ <p>The pipe symbol works the same way as with the paradigmatic alternation, but supports sequences of different length as operands. The above query for <code>der alte Mann</code> and <code>der junge Mann</code> can therefor be reformulated as:</p>
+
+ %= kalamar_tut_query poliqarp => 'der (junge | alte) Mann'
+
+ <h4 id="tut-syntagmatic-operators-repetitions">Repetition</h4>
+
+ <p>Repetitions in Poliqarp are realized as in <%= kalamar_tut_link_to 'regular expressions', '/tutorial/regular-expressions' %>, by giving quantifieres in curly brackets.</p>
+ <p>To search for a sequence of three occurrences of <code>der</code>, you can formulate your query in any of the following ways - they will have the same results:</p>
+
+ %= kalamar_tut_query poliqarp => 'der der der'
+ %= kalamar_tut_query poliqarp => 'der{3}'
+ %= kalamar_tut_query poliqarp => '[orth=der]{3}'
+
+ <p>In difference to regular expressions, the repetition operation won't refer to the match but to the pattern given. So the following query will give you a sequence of three words having the term <code>der</code> as a substring - but the words don't have to be identical. The following query for example will match a sequence of three words all starting with <code>la</code>.</p>
+
+ %= kalamar_tut_query poliqarp => '"la.*?"/i{3}'
+
+ <p>The same is true for annotations. The following query will find a sequence of 3 to 4 adjectives as annotated by the TreeTagger foundry, that is preceded by the lemma <code>ein</code> as annotated by the default foundry and followed by a noun as annotated by the XIP foundry. The adjectives do not have to be identical though.</p>
+
+ %= kalamar_tut_query poliqarp => '[base=ein][tt/p=ADJA]{3,4}[xip/p=NOUN]'
+
+ <p>In addition to numbered quantities, it is also possible to pass repetition information as Kleene operators <code>?</code>, <code>+</code>, and <code>+</code>.</p>
+
+ <p>To search for a sequence of the lemma <code>der</code> followed by the lemma <code>baum</code> as annotated by the base foundry, but allowing an optional adjective as annotated by the TreeTagger foundry in between, you can search for:</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA]?[base=Baum]'
+
+ <p>This query is identical to the numbered quantification of:</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA]{,1}[base=Baum]'
+
+ <p>To search for the same sequences but with unlimited adjectives as annotated by the TreeTagger foundry in between, you can use the Kleene Star:</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA]*[base=Baum]'
+
+ <p>And to search for this sequence but with at least one adjective in between, you can use the Kleene Plus (all queries are identical):</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA]+[base=Baum]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA]{1,}[base=Baum]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '[base=die][tt/pos=ADJA][tt/pos=ADJA]*[base=Baum]', cutoff => 1
+
+ <blockquote class="warning">
+ <p>Repetition operators like <code>{,4}</code>, <code>?</code>, and <code>*</code> make segments or groups of segments optional. In case these queries are used separated and not in a sequence (and there are no mandatory segments in the query), you will be warned by the system that your query won't be treated as optional.</p>
+ <p>Keep in mind that optionality may be somehow <i>inherited</i>, for example when you search for <code>(junge|alte)?|tote</code>, one segment of the alternation is optional, which makes the whole query optional as well.</p>
+ </blockquote>
+
+ <p>Repetition can also be used to express distances between segments by using <a href="#empty-segments">empty segments</a>.</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][][base=Baum]'
+ %= kalamar_tut_query poliqarp => '[base=die][]{2}[base=Baum]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '[base=die][]{2,}[base=Baum]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '[base=die][]{,3}[base=Baum]', cutoff => 1
+
+ <p>Of course, Kleene operators can be used with empty segments as well.</p>
+
+ %= kalamar_tut_query poliqarp => '[base=die][]?[base=Baum]'
+ %= kalamar_tut_query poliqarp => '[base=die][]*[base=Baum]', cutoff => 1
+ %= kalamar_tut_query poliqarp => '[base=die][]+[base=Baum]', cutoff => 1
+
+ <h4>Position</h4>
+
+ <p>Sequences as shown above can all be nested in further complex queries and treated as subqueries (see <a href="#tut-class-operators">class operators</a> on how to later access these subqueries directly).</p>
+ <p>Positional operators compare two matches of subqueries and will match, in case a certain condition regarding the position of both is true.</p>
+ <p>The <code>contains()</code> operation will match, when a second subquery matches inside the span of a first subquery.</p>
+
+ %= kalamar_tut_query poliqarp => 'contains(<s>, [tt/p=KOUS])', cutoff => 1
+
+ <p>The <code>startsWith()</code> operation will match, when a second subquery matches at the beginning of the span of a first subquery.</p>
+
+ %= kalamar_tut_query poliqarp => 'startsWith(<s>, [tt/p=KOUS])', cutoff => 1
+
+ <p>The <code>endsWith()</code> operation will match, when a second subquery matches at the end of the span of a first subquery.</p>
+
+ %= kalamar_tut_query poliqarp => 'endsWith(<s>, [opennlp/p=NN])', cutoff => 1
+
+ <p>The <code>matches()</code> operation will match, when a second subquery has the exact same span of a first subquery.</p>
+
+ %= kalamar_tut_query poliqarp => 'matches(<s>,[tt/p=CARD][tt/p="N.*"])', cutoff => 1
+
+ <p>The <code>overlaps()</code> operation will match, when a second subquery has an overlapping span with the first subquery.</p>
+
+ %= kalamar_tut_query poliqarp => 'overlaps([][tt/p=ADJA],{1:[tt/p=ADJA]}[])', cutoff => 1
+
+ <blockquote class="warning">
+ <p>Positional operators are still experimental and may change in certain aspects in the future (although the behaviour defined is intended to be stable). There is also known incorrect behaviour which will be corrected in future versions.</p>
+ <p>Optional operands in position operators, like in <code>contains(<s>,[orth=Baum]*)</code>, have to be mandatory at the moment and will be reformulated to occur at least once.</p>
+ <p>This behaviour may change in the future.</p>
+ </blockquote>
+
+ <!--
+ <blockquote>
+ <p>The KorAP implementation of Poliqarp also supports the postfix <code>within</code> operator, that works similar to the <code>contains()</code> operator, but is not nestable.</p>
+ </blockquote>
+ -->
+
+</section>
+
+<section id="tut-class-operators">
+ <h3>Class Operators</h3>
+
+ <p>Classes are used to group sub matches by surrounding curly brackets and a class number <code>{1:...}</code>. Classes can be used to refer to sub matches in a query, similar to captures in regular expressions. In Poliqarp+ classes have multiple purposes, with highlighting being the most intuitive one:</p>
+
+ %= kalamar_tut_query poliqarp => 'der {1:{2:[]} Mann}'
+
+ %#= kalamar_tut_query poliqarp => 'der {1:{2:[]{1,4}} {3:Baum}} {4:[]}'
+
+ <p>In KorAP classes can be defined from 1 to 128. In case a class number is dismissed, the class defaults to the class number 1: <code>{...}</code> is equal to <code>{1:...}</code>.</p>
+
+ <h4>Match Modification</h4>
+
+ <p>Based on classes, matches may be modified. The <code>focus()</code> operator restricts the span of a match to the boundary of a certain class.</p>
+
+ %= kalamar_tut_query poliqarp => 'focus(der {Baum})'
+
+ <p>The query above will search for the sequence <code>der Baum</code> but the match will be limited to <code>Baum</code>. You can think of <code>der</code> in this query as a positive look-behind zero-length assertion in regular expressions.</p>
+
+ <p>But focus is way more useful if you are searching for matches without knowing the surface form. For example, to find all terms between the words "der" and "Mann" you can search:</p>
+
+ %= kalamar_tut_query poliqarp => 'focus(der {[]} Mann)'
+
+ <p>This will limit the match to all interesting terms in between "der" and "Mann". Or you may want to search for all words following the sequence "der alte und" immediately:</p>
+
+ %= kalamar_tut_query poliqarp => 'focus(der alte und {[]})'
+
+ <!--
+ <p><code>focus()</code> is especially useful if you are searching for matches in certain areas, for example in quotes using positional operators.
+While not being interested in the whole quote as a match, you can focus on what's really relevant to you.</p>
+
+ %= kalamar_tut_query poliqarp => 'focus(1:contains(er []{,10} sagte, 1{Baum}))'
+ -->
+
+ <p>In case a class number is dismissed, the focus operator defaults to the class number 1: <code>focus(...)</code> is equal to <code>focus(1: ...)</code>.</p>
+
+ <blockquote class="warning">
+ <p>As numbers in curly brackets can be ambiguous in certain circumstances, for example <code>[]{3}</code> can be read as either "any word repeated three times" or "any word followed by the number 3 highlighted as class number 1", numbers should always be expressed as <code>[orth=3]</code> for the latter case.</p>
+ </blockquote>
+</section>
diff --git a/templates/doc/ql/regexp.html.ep b/templates/doc/ql/regexp.html.ep
new file mode 100644
index 0000000..efbd41d
--- /dev/null
+++ b/templates/doc/ql/regexp.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Regular Expressions';
+
+<h2>Regular Expressions</h2>
+
+%= doc_uc
diff --git a/templates/doc/ql/wildcards.html.ep b/templates/doc/ql/wildcards.html.ep
new file mode 100644
index 0000000..4ab29e2
--- /dev/null
+++ b/templates/doc/ql/wildcards.html.ep
@@ -0,0 +1,5 @@
+% layout 'main', title => 'KorAP: Wildcards';
+
+<h2>Wildcards</h2>
+
+%= doc_uc