initial commit

This commit is contained in:
Oleg Belyaev 2025-03-21 14:14:03 +03:00
parent cee3efab31
commit 71219733bd
31 changed files with 9242 additions and 0 deletions

264
xq/abv-mod.xqm Normal file
View file

@ -0,0 +1,264 @@
module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod';
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
declare function abv-m:normalize-str($str as xs:string?)
as xs:string? {
$str => translate('
','') => normalize-space()
};
declare function abv-m:sortKey($word as xs:string)
as xs:string {
$word => replace('-','')
=> replace('\(','')
=> replace('\)','')
=> replace('́','') (: combining acute :)
=> replace('\*','')
=> replace('a','/')
=> replace('A', '/')
=> replace('ā', '/')
=> replace('Ā', '/')
=> replace('á', '/')
=> replace('Á', '/')
=> replace('ā́', '/')
=> replace('Ā́', '/')
=> replace('æ', '1')
=> replace('Æ', '1')
=> replace('ǽ', '1')
=> replace('Ǽ', '1')
=> replace('b', '2')
=> replace('B', '2')
=> replace('cʼ', '4')
=> replace('Cʼ', '4')
=> replace('c', '3')
=> replace('C', '3')
=> replace('d', '5')
=> replace('D', '5')
=> replace('ʒ', '6')
=> replace('Ʒ', '6')
=> replace('e', '7')
=> replace('E', '7')
=> replace('é', '7')
=> replace('É', '7')
=> replace('f', '8')
=> replace('F', '8')
=> replace('g[˳₀ₒ]', '9')
=> replace('G[˳₀ₒ]', '9')
=> replace('g', '9')
=> replace('G', '9')
=> replace('ǵ', '9')
=> replace('Ǵ', '9')
=> replace('ǧ[˳₀ₒ]', 'A')
=> replace('Ǧ[˳₀ₒ]', 'A')
=> replace('ǧ', 'A')
=> replace('Ǧ', 'A')
=> replace('i', 'B')
=> replace('I', 'B')
=> replace('í', 'B')
=> replace('Í', 'B')
=> replace('ī', 'B')
=> replace('Ī', 'B')
=> replace('ī́', 'B')
=> replace('Ī́', 'B')
=> replace('j', 'D')
=> replace('J', 'D')
=> replace('kʼ[˳₀ₒ]', 'F')
=> replace('Kʼ[˳₀ₒ]', 'F')
=> replace('kʼ', 'F')
=> replace('Kʼ', 'F')
=> replace('k[˳₀ₒ]', 'E')
=> replace('K[˳₀ₒ]', 'E')
=> replace('k', 'E')
=> replace('K', 'E')
=> replace('ḱʼ', 'F')
=> replace('Ḱʼ', 'F')
=> replace('ḱ', 'E')
=> replace('Ḱ', 'E')
=> replace('l', 'H')
=> replace('L', 'H')
=> replace('m', 'I')
=> replace('M', 'I')
=> replace('n', 'J')
=> replace('N', 'J')
=> replace('o', 'K')
=> replace('O', 'K')
=> replace('ó', 'K')
=> replace('Ó', 'K')
=> replace('pʼ', 'M')
=> replace('Pʼ', 'M')
=> replace('p', 'L')
=> replace('P', 'L')
=> replace('q[˳₀ₒ]', 'N')
=> replace('Q[˳₀ₒ]', 'N')
=> replace('q', 'N')
=> replace('Q', 'N')
=> replace('r', 'O')
=> replace('R', 'O')
=> replace('s', 'P')
=> replace('S', 'P')
=> replace('tʼ', 'R')
=> replace('Tʼ', 'R')
=> replace('t', 'Q')
=> replace('T', 'Q')
=> replace('u', 'S')
=> replace('U', 'S')
=> replace('ú', 'S')
=> replace('Ú', 'S')
=> replace('ū', 'S')
=> replace('Ū', 'S')
=> replace('ū́', 'S')
=> replace('Ū́', 'S')
=> replace('v', 'T')
=> replace('V', 'T')
=> replace('w', 'U')
=> replace('W', 'U')
=> replace('x[˳₀ₒ]', 'V')
=> replace('X[˳₀ₒ]', 'V')
=> replace('x', 'V')
=> replace('X', 'V')
=> replace('y', 'W')
=> replace('Y', 'W')
=> replace('ý', 'W')
=> replace('Ý', 'W')
=> replace('z', 'X')
=> replace('Z', 'X')
};
declare function abv-m:sort-collection($docs as document-node()+) {
sort($docs, (), function($d) {
abv-m:sortKey($d/tei:entry[1]/tei:form[1]/tei:orth[1]/text()[1]) })
};
declare function abv-m:sort-nodes($docs as node()+) {
sort($docs, (), function($d) {
abv-m:sortKey($d/text()) })
};
(: Apply XSL transformations to create a TEI-conformant <entry/> element,
or a sequence thereof :)
declare function abv-m:make-lng($src as document-node()+,
$lang as xs:string)
as node()+ {
for $doc in $src
let $del_lang := if ($lang = 'en') then 'ru' else 'en'
return ($doc => xslt:transform(doc('../xsl/strip-space.xsl'))
=> xslt:transform(doc('../xsl/delete-lang.xsl'),
{'lang': $del_lang})
=> xslt:transform(doc('../xsl/insert-refs.xsl'),
{'lookup-raw':
serialize(doc('abaevdict_index/lookup.xml')),
'biblio-raw':
serialize(doc('abaevdict_index/abaev_biblio.xml')),
'bib-lang': $lang})
=> xslt:transform(doc('../xsl/insert-langs.xsl'),
{'name-lang': $lang})
=> xslt:transform(doc('../xsl/standardize.xsl'),
{'standardize-lang': $lang})
=> xslt:transform(doc('../xsl/change-default-lang.xsl'),
{'default-lang': $lang}))/tei:TEI/tei:text/tei:body/tei:entry[1]
};
declare function abv-m:insert-full-lang($abbr as node(), $lang as xs:string) {
let $flang := tokenize($abbr/@data-lang,',')
return $abbr transform with {
insert node attribute title {
string-join(doc('abaevdict_index/langnames.xml')/csv[1]/record[code/text() = $flang]/*[name()=$lang]/text(),', ')
} as first into .
}
};
declare function abv-m:make-html($src as document-node()+,
$lang as xs:string)
as node()+ {
for $doc in $src
let $html := xslt:transform($doc,
doc('../xsl/abaev2html.xsl'), {'lang': $lang})
return $html transform with {for $abbr in //abbr
let $newabbr := abv-m:insert-full-lang($abbr,$lang)
return replace node $abbr with $newabbr}
};
(: Function to generate a map for each mentioned in a document,
to be later fed to a geo map :)
declare function abv-m:make-geomap($doc as document-node(), $lang as xs:string) {
(: let $id := $doc/tei:entry/@xml:id :)
let $list := for $mlang in distinct-values($doc//tei:mentioned[not(tei:mentioned)]/@xml:lang)
let $ment := $doc//tei:mentioned[not(tei:mentioned) and @xml:lang=$mlang][1]
let $linfo := doc(`abaevdict_index/langnames.xml`)/csv[1]/record[code/text() = $mlang]
where $mlang != 'os'
and not(starts-with($mlang,'os-'))
and $linfo/long[1] != '-99'
and $linfo/lat[1] != '-99'
and $ment[tei:w]
return {
'text': ($ment/tei:w/text())[1],
'hovertext': string($linfo/*[name()=$lang][1]/text()),
'lon': xs:float($linfo/long[1]),
'lat': xs:float($linfo/lat[1])
}
let $map := map:merge(({'type': 'scattergeo',
'mode': 'markers+text',
'hoverinfo': 'text',
'textposition': 'top center',
'marker': {'size': 7,
'line': {'width': 1}
}
},
for $k in map:keys($list[1])
let $seq := for $e in $list return $e($k)
return map:entry($k, array { $seq })))
return $map
};
declare function abv-m:langname-by-id($id as xs:string, $lang as xs:string) {
doc('abaevdict_index/langnames.xml')/csv[1]/record[code/text()=$id]/*[name()=$lang]/text()
};
declare function abv-m:entry-form-by-id($id as xs:string) {
doc(`abaevdict_index/lookup.xml`)/tei:table[1]/tei:entry[@xml:id=$id]/text()
};

12
xq/gen-lng-entries.xq Normal file
View file

@ -0,0 +1,12 @@
declare default element namespace "http://www.tei-c.org/ns/1.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
let $langs := ('ru', 'en')
for $lang in $langs
for $doc in abv-m:make-lng(collection('abaevdict'), $lang)
let $id := $doc/@xml:id
return db:put(`abaevdict_{$lang}`, $doc, `xml/{$id}.xml`)

10
xq/gen-lng-html.xq Normal file
View file

@ -0,0 +1,10 @@
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
let $langs := ('ru', 'en')
for $lang in $langs
for $doc in abv-m:make-html(collection(`abaevdict_{$lang}/xml`), $lang)
return db:put(`abaevdict_{$lang}`, $doc, `html/{$doc/article[1]/@id}.html`)

115
xq/gen-mentioned-index.xq Normal file
View file

@ -0,0 +1,115 @@
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
declare function local:get-gloss($ment as node())
as xs:string* {
if (name($ment) = 'mentioned') then (
if (count($ment/tei:gloss) > 0)
then $ment/tei:gloss/tei:q/text()
else local:get-gloss($ment/..)
)
else ()
};
declare function local:get-ment($ment as node(), $id as xs:string)
as map(xs:string, map(xs:string, map(xs:string, item()*)))* {
for $w in $ment/tei:w/text()
return map{$w : map{$id :
map {'gloss': local:get-gloss($ment),
'node': db:node-id($ment) }
}
}
};
declare variable $metalang external := 'en';
let $docs := collection(`abaevdict_{$metalang}/xml`)
(: let $docs := doc(`abaevdict_{$metalang}/xml/entry_mad.xml`) :)
(: Create sequence of isolated indices for each entry :)
let $langs-seq := for $doc in $docs
let $ments := $doc//tei:mentioned[tei:w]
let $id := $doc/tei:entry[1]/@xml:id
for $ment in $ments
return map:build($ment, keys := fn {./@xml:lang },
value := fn { local:get-ment(., $id) } )
(: Merge these sequences into one, creating a list containing duplicates :)
let $langs-merged := map:merge($langs-seq, {'duplicates': 'combine'})
(: For each word, merge occurrence information :)
let $langs-index := map:merge(
for $lang in map:keys($langs-merged)
let $words := map:merge($langs-merged($lang),
{'duplicates': 'combine'}
)
let $words-m := map:merge(for $w in map:keys($words)
return {$w: map:merge($words($w),
{'duplicates': 'combine'}
)})
return {$lang: $words-m}
)
(: Now we have to go through these languages and merge duplicates
for each of them :)
(: let $lang-index := map:merge(
for $lang in map:keys($langs-merged)
let $linfo := map:merge($langs-merged($lang),
{'duplicates': 'combine'})
let $linfo-m := map:merge(
for $w in map:keys($linfo)
return map{$w: {'entries':
distinct-values($winfo('entries')),
'glosses':
distinct-values($winfo('glosses'))}}
)
return {$lang: $linfo-m}
) :)
(: return $langs-index :)
(: for $lang in map:keys($lang-index)
for $w in map:keys($lang-index($lang))
where count($lang-index($lang)($w)('entries')) > 1
return ($lang,$w, $lang-index($lang)($w)) :)
return
<lang-index>
{
for $lang in map:keys($langs-index)
let $words := $langs-index($lang)
order by abv-m:langname-by-id($lang, $metalang)
return
<lang id='{$lang}'>
{
for $w in map:keys($words)
let $wn := abv-m:normalize-str($w)
order by $wn
return
<word text="{$wn}">
{
for $e in map:keys($words($w))
return
<entry id="{$e}">
{
for $ref in $words($w)($e)
return
<ref node-id="{$ref('node')}">
{
for $g in $ref('gloss')
return
if ($g != '') then <gloss text="{$g}"/> else ()
}
</ref>
}
</entry>
}
</word>
}
</lang>
}
</lang-index>

24
xq/make-lookup.xq Normal file
View file

@ -0,0 +1,24 @@
declare default element namespace "http://www.tei-c.org/ns/1.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
declare function local:genLookupEntry($doc as document-node())
as element()?
{
let $node := $doc/tei:TEI/tei:text/tei:body/tei:entry
let $phon := $node/tei:form[1]/tei:orth[1]/text()[1]
return element entry {
attribute xml:id { $node/@xml:id },
attribute filename { db:path($doc) },
if ($node/@n) then attribute n {$node/@n} else (),
text { $phon }
}
};
let $tbl := <table>
{for $doc in collection('abaevdict')
return local:genLookupEntry($doc)}
</table>
return db:put('abaevdict_index', $tbl, 'lookup.xml')

4
xq/parse-langnames.xq Normal file
View file

@ -0,0 +1,4 @@
let $text := file:read-text('./basex/webapp/csv/langnames.csv')
return db:put('abaevdict_index',
csv:parse($text, { 'header': true() }),
'langnames.xml')

175
xq/restx_api.xq Normal file
View file

@ -0,0 +1,175 @@
declare namespace api = 'http://ossetic-studies.org/ns/abaevdict-api';
declare namespace tei = "http://www.tei-c.org/ns/1.0";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
(: ======================================================= :)
(: ==================== API STUFF ======================== :)
(: ======================================================= :)
declare option output:method 'json';
declare option output:json "format=xquery";
declare variable $langs-index := doc('abaevdict_index/langnames.xml');
declare variable $lookup := doc('abaevdict_index/lookup.xml');
(: Get the mentioned index for the right metalanguage :)
declare function api:ment-index($db-lang as xs:string) {
doc(`abaevdict_index/mentioned_{$db-lang}.xml`)
};
(: Short entry info (only forms for now). Hash is used because URLs don't handle
some Unicode characters very well in this system :)
declare function api:entry-info-short($n as node())
as map(xs:string, xs:string) {
map{'id': string(hash($n/@xml:id)), 'xmlid': $n/@xml:id, 'form': $n/text()}
};
(: Short language info -- for the language list :)
declare function api:lang-info-short($n as node(), $db-lang as xs:string) {
map{
'id': $n/code/text(),
'glottolog': $n/glottolog/text(),
'name': map{'full': if ($db-lang = 'ru') then $n/ru/text() else $n/en/text(),
'abbr': if ($db-lang = 'ru') then $n/ru/text() else $n/en_abbr/text()}
}
};
(: Longer info -- for individual languages :)
declare function api:lang-info-full($n as node(), $db-lang as xs:string) {
map:merge(
(api:lang-info-short($n, $db-lang),
map{'words':
array:build(api:ment-index($db-lang)/lang-index[1]/lang[@id=$n/code]/word,
api:word-info-short#1)
}
)
)
};
declare function api:word-info-short($n as node()) {
let $text := xs:string($n/@text)
return map{
(: I am using a hash function as ID, because the words are uniquely
identified within a language by their text. And the mentioned index is not
persistent enough (at least yet) to use persistent ids :)
'id': string(hash($text)),
'text': $text
}
};
declare function api:word-info-long($n as node()) {
map:merge(
(
api:word-info-short($n),
map{
'entries': array:build($n/entry,
fn {
map{'id': string(hash(./@id)),
'xmlid': string(./@id),
'refs': array:build(./ref,
fn {
map:merge((
map:entry('node-id', string(./@node-id)),
if(./gloss) then
{'glosses': array:build(distinct-values(./gloss/@text), string#1)}
else ()
)
)
})
}
}
)
(: 'nodes': array:build(string($n/ref/@node-id)),
'glosses': array:build(string($n/gloss/@text)) :)
}
)
)
};
(: RETURN JSON FOR PLOTLY MAP :)
(: English as default language :)
declare %rest:path("dict/map-info/{$entry}")
%rest:GET
function api:map-info($entry) {
(: In this case we do not redirect, but simply give the JSON via
another function :)
api:map-info('en', $entry)
};
(: This has to be remade to use the /api path. But keep it like this for now :)
declare %rest:path("{$lang}/dict/map-info/{$entry}")
%rest:GET
function api:map-info($lang, $entry) {
let $ments := abv-m:make-geomap(doc(`abaevdict_{$lang}/xml/{$entry}.xml`),
$lang)
return $ments
};
(: API FOR THE MENTIONED INDEX :)
(: Default to English :)
declare %rest:path("/api/{$path=.+}")
%rest:GET
function api:default($path as xs:string) {
web:forward(`/en/api/{$path}`)
};
(: Get languages :)
declare %rest:path("{$db-lang}/api/languages")
%rest:GET
function api:langs($db-lang as xs:string := 'en') {
array:build(
$langs-index/csv[1]/record,
api:lang-info-short(?,$db-lang)
)
};
(: Get one language :)
declare %rest:path("{$db-lang}/api/languages/{$lang}")
%rest:GET
function api:langs-lang($db-lang as xs:string, $lang as xs:string) {
api:lang-info-full(
$langs-index/csv[1]/record[code=$lang], $db-lang
)
};
(: Get words for a language :)
declare %rest:path("{$db-lang}/api/languages/{$lang}/words")
%rest:GET
function api:langs-lang-words($db-lang as xs:string, $lang as xs:string) {
array:build(api:ment-index($db-lang)/lang-index[1]/lang[@id=$lang]/word,
api:word-info-short#1)
};
(: Get info on a particular word.
Db-lang is a placeholder, it does nothing here, used only for consistency :)
declare %rest:path("{$db-lang}/api/languages/{$lang}/words/{$word-id}")
%rest:GET
function api:langs-lang-words-word($db-lang as xs:string,
$lang as xs:string,
$word-id as xs:string) {
api:word-info-long(
api:ment-index($db-lang)/lang-index[1]/lang[@id=$lang]/word[string(hash(@text))=$word-id]
)
};
(: Entry info (only form for now) :)
declare %rest:path("{$db-lang}/api/entries")
%rest:GET
function api:entries($db-lang as xs:string) {
array:build(
$lookup/tei:table[1]/tei:entry,
api:entry-info-short#1
)
};
declare %rest:path("{$db-lang}/api/entries/{$entry-id}")
%rest:GET
function api:entries($db-lang as xs:string,
$entry-id as xs:string) {
api:entry-info-short(
$lookup/tei:table[1]/tei:entry[string(hash(@xml:id))=$entry-id])
};
0

122
xq/restx_dict.xq.old Normal file
View file

@ -0,0 +1,122 @@
module namespace page = 'http://ossetic-studies.org/ns/abaevdict-site';
declare namespace tei = "http://www.tei-c.org/ns/1.0";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
declare variable $page:items as xs:integer := 20;
declare %rest:path("{$lang}/dict/page{$p}")
(: %rest:GET :)
%output:method("html")
%output:html-version('5')
function page:dict($lang, $p) {
let $pagetotal := ceiling(count(collection('abaevdict_en')) div $page:items)
let $sorted := abv-m:sort-collection(collection(`abaevdict_{$lang}`))
return
<html>
<head>
<script src="/static/jquery-3.7.1.min.js">
</script>
<script src="/static/infinite-scroll.pkgd.min.js">
</script>
<script src="/static/plotly-3.0.1.min.js" charset="utf-8"></script>
<script src="/static/abaev.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css"/>
<link rel="stylesheet" href="{web:create-url('/static/abaev-html.css')}"/>
<title>Abaev</title>
</head>
<body>
<header>
<nav>
<ul>
<li><strong>Abaevdict</strong></li>
</ul>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Dictionary</a></li>
<li><a href="#">Index</a></li>
<li><a href="#">References</a></li>
</ul>
</nav>
</header>
<button id="open-leftbar">
{html:doc('../static/chevron-right.svg')}
</button>
<button id="close-leftbar">
{html:doc('../static/chevron-left.svg')}
</button>
<aside id="leftbar">
<input type="text" id="filter-entries" placeholder="Quick filter…"/>
<nav id="entrylist">
<ul>
{for $doc in $sorted
return <li id="link_{$doc/tei:entry[1]/@xml:id}">
<a href="by-id/{$doc/tei:entry[1]/@xml:id}">
{$doc/tei:entry[1]/tei:form[1]/tei:orth[1]/text()}
</a>
</li>
}
</ul>
</nav>
</aside>
<main>
{for $doc at $i in $sorted
where $i > ($p - 1) * $page:items and $i <= $p * $page:items
let $html := xslt:transform($doc,
doc('../xsl/abaev2html.xsl'), {'lang': $lang})
return $html}
</main>
<footer>
<nav class="pagination">
<ul>
<li>
{if ($p > 1) then <a href="page{$p - 1}">Previous page</a> else ()}
</li>
</ul>
<!-- <ul><li>Page {$p} of {$pagetotal}</li></ul> -->
<ul>
<li>
{if ($p < $pagetotal) then
<a class="pagination__next" href="page{$p + 1}">Next page</a> else ()}
</li>
</ul>
</nav>
</footer>
<dialog id="modal_map">
<article>
<header><button class="abv-close-map" aria-label="Close" rel="prev"></button>
<p>Map</p>
</header>
<p>
<div id="map_display" style="width:100%;height:80%;"></div>
</p>
<footer><button class="abv-close-map">Close</button></footer>
</article>
</dialog>
</body>
</html>
};
declare %rest:path("{$lang}/dict/by-id/{$id}")
(: %rest:GET :)
%output:method("html")
%output:html-version('5')
function page:by-id($lang, $id) {
let $seq := abv-m:sort-collection(collection(`abaevdict_{$lang}`))
let $doc-index := index-of($seq, $seq[tei:entry[@xml:id=`{$id}`]])
let $pagenum := ceiling($doc-index div $page:items)
return web:redirect(`../page{$pagenum}`, {}, web:decode-url($id))
};
declare %rest:path("{$lang}/dict/map-info/{$entry}")
%rest:produces("application/json")
%rest:GET function page:map-info($lang, $entry) {
let $ments := abv-m:make-geomap(doc(`abaevdict_{$lang}/{$entry}.xml`),
$lang)
return json:serialize($ments, {'format': 'xquery'})
};

219
xq/restx_dict_cached.xq Normal file
View file

@ -0,0 +1,219 @@
module namespace page = 'http://ossetic-studies.org/ns/abaevdict-site';
declare namespace tei = "http://www.tei-c.org/ns/1.0";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
(: =========================================================== :)
(: ================== GLOBAL VARIABLES ======================= :)
(: =========================================================== :)
(: Number of items per page :)
declare variable $page:items as xs:integer := 20;
(: These variables are declared in module scope because they are needed in
different places, but they are still dynamically evaluated :)
declare variable $page:lookup := doc('abaevdict_index/lookup.xml')/tei:table/tei:entry;
declare variable $page:total := ceiling(count($page:lookup) div $page:items);
declare variable $page:sorted := abv-m:sort-nodes($page:lookup);
(: =============================================================== :)
(: ======================= COMMON STUFF ========================== :)
(: =============================================================== :)
declare function page:head($title as xs:string, $script as node()* := ()) {
<head>
<script src="/static/jquery-3.7.1.min.js">
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.classless.min.css"/>
<link rel="stylesheet" href="{web:create-url('/static/abaev-html.css')}"/>
{$script}
<title>{$title}</title>
</head>
};
(: Navigation header :)
declare function page:header() {
<header>
<nav>
<ul>
<li><strong>Abaevdict</strong></li>
</ul>
<ul>
<li><a href="./home">Home</a></li>
<li><a href="./dict">Dictionary</a></li>
<li><a href="./index">Index</a></li>
<li><a href="#">References</a></li>
</ul>
</nav>
</header>
};
(: =============================================================== :)
(: ======================= THE PAGES ============================= :)
(: =============================================================== :)
(: If no language defined, default to English :)
declare %rest:path("dict")
%output:method("html")
%output:html-version('5')
function page:dict() {
web:forward('/en/dict')
};
(: The main dictionary view :)
declare %rest:path("{$lang}/dict")
%rest:query-param("page","{$p}", 1)
%output:method("html")
%output:html-version('5')
function page:dict($lang, $p) {
<html>
{page:head('HEDO Dictionary',
(<script src="/static/infinite-scroll.pkgd.min.js">
</script>,
<script src="/static/plotly-3.0.1.min.js" charset="utf-8"></script>,
<script src="/static/abaev.js"></script>))}
<body>
{page:header()}
<!-- Sidebar with entry list -->
<button id="open-leftbar">
{html:doc('../static/chevron-right.svg')}
</button>
<button id="close-leftbar">
{html:doc('../static/chevron-left.svg')}
</button>
<aside id="leftbar">
<input type="text" id="filter-entries" placeholder="Quick filter…"/>
<nav id="entrylist">
<ul>
{for $doc in $page:sorted
return <li id="link_{$doc/@xml:id}">
<a href="./dict/{$doc/@xml:id}">
{$doc/text()}
</a>
</li>
}
</ul>
</nav>
</aside>
<!-- The dictionary itself. The entries are displayed as articles retrieved
from the database in HTML. On-the-fly generation is only when required -->
<main>
{for $doc at $i in $page:sorted
where $i > ($p - 1) * $page:items and $i <= $p * $page:items
let $html := doc(`abaevdict_{$lang}/html/{$doc/@xml:id}.html`)
return $html}
</main>
<!-- Footer for page navigation -->
<footer>
<nav class="pagination">
<ul>
<li>
{if ($p > 1) then <a href="?page={$p - 1}">Previous page</a> else ()}
</li>
</ul>
<!-- <ul><li>Page {$p} of {$page:total}</li></ul> -->
<ul>
<li>
{if ($p < $page:total) then
<a class="pagination__next" href="?page={$p + 1}">Next page</a> else ()}
</li>
</ul>
</nav>
</footer>
<!-- Modal for map display -->
<dialog id="modal_map">
<article>
<header><button class="abv-close-map" aria-label="Close" rel="prev"></button>
<p>Map</p>
</header>
<p>
<div id="map_display" style="width:100%;height:80%;"></div>
</p>
<footer><button class="abv-close-map">Close</button></footer>
</article>
</dialog>
</body>
</html>
};
(: == ENTRY BY ID == :)
(: English as default language :)
declare %rest:path("dict/{$id}")
%output:method("html")
%output:html-version('5')
function page:by-id($id) {
page:by-id('en',$id)
};
declare %rest:path("{$lang}/dict/{$id}")
%output:method("html")
%output:html-version('5')
function page:by-id($lang, $id) {
let $doc-index := index-of($page:sorted, $page:sorted[@xml:id=`{$id}`])
let $pagenum := ceiling($doc-index div $page:items)
return web:redirect('../dict', {'page': $pagenum}, web:decode-url($id))
};
(: Mentioned index :)
declare %rest:path("{$lang}/index")
%output:method("html")
%output:html-version('5')
function page:index($lang) {
let $mlangs := doc(`abaevdict_index/langnames.xml`)/csv[1]/record
return
<html>
{page:head('HEDO Index', <script src="/static/abaev-index.js"></script>)}
<body>
{page:header()}
<main>
<div class="index">
<div class="langs">
<label>Languages</label>
<select id="abv-select-lang" size="99999">
{
for $mlang in $mlangs
let $mlang-id := $mlang/code/text()
let $mlang-name := if ($lang = 'ru') then $mlang/ru/text() else $mlang/en/text()
where $mlang-name != ''
return
<option value="{$mlang-id}">
{
$mlang-name
}
</option>
}
</select>
</div>
<div class="forms">
<Label>Forms</Label>
<select id="abv-select-word" size="99999">
</select>
</div>
<div class="entries">
<Label>Entries</Label>
<select id="abv-select-entry" size="99999">
</select>
</div>
</div>
</main>
</body>
</html>
};
(: Default to English :)
declare %rest:path("index")
%output:method("html")
%output:html-version('5')
function page:index() {
page:index('en')
};

60
xq/test.xq Normal file
View file

@ -0,0 +1,60 @@
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace abv = "http://ossetic-studies.org/ns/abaevdict";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
let $doc := db:get('abaevdict_en','/xml/entry_az.xml')
return string(abv-m:make-html($doc, 'ru')/article[1]/@id)
(: let $nid := db:node-id($doc/tei:entry[1]/tei:note[1]) :)
(: return $nid :)
(: return xquery:eval('declare namespace tei = "http://www.tei-c.org/ns/1.0";//tei:note',{'': $doc}) :)
(: abv-m:make-html(doc('abaevdict_en/xml/entry_sæpp.xml'), 'en') :)
(: db:node-id(db:get-id('abaevdict_index',1307388)) :)
(: import module namespace api = 'http://ossetic-studies.org/ns/abaevdict-api' at './restx_api.xq'; :)
(: abv-m:make-html(doc('abaevdict_en/xml/entry_az.xml')//tei:mentioned,'en') :)
(: abv-m:langname-by-id('inc-x-old-vaidika','en') :)
(: SERIALIZE AS JSONML :)
(: json:serialize(doc('abaevdict_index/mentioned.xml'), {'format': 'jsonml'}) :)
(: GENERATE MENTIONED INDEX :)
(: let $langs := ('en', 'ru')
for $lang in $langs
let $index := xquery:eval(xs:anyURI('gen-mentioned-index.xq'), {'metalang': $lang})
return db:put('abaevdict_index', $index, `mentioned_{$lang}.xml`) :)
(: GENERATE ENGLISH/RUSSIAN TEI FOR ONE ENTRY :)
(: let $langs := ('en','ru')
for $lang in $langs
for $doc in abv-m:make-lng(doc('abaevdict/abaev_-ston.xml'), $lang)
let $id := $doc/@xml:id
return db:put(`abaevdict_{$lang}`, $doc, `xml/{$id}.xml`) :)
(: GENERATE HTML FOR ONE ENTRY :)
(: let $langs := ('en','ru')
for $lang in $langs
let $doc := abv-m:make-html(doc(`abaevdict_{$lang}/xml/entry_-ston.xml`), $lang)
let $id := $doc/article[1]/@id
return db:put(`abaevdict_{$lang}`, $doc, `html/{$id}.html`) :)
(: TEST HTML GEN :)
(: abv-m:make-html(doc('abaevdict_en/xml/entry_abūxyn.xml'),'en') :)
(: GENERATE ENGLISH/RUSSIAN HTML :)
(: for $doc in abv-m:make-html(collection('abaevdict_ru/xml'), 'ru')
return db:put('abaevdict_ru', $doc, `html/{$doc/article[1]/@id}.html`) :)
(: TEST GEOMAP FOR ONE ENTRY :)
(: let $doc := doc('abaevdict_en/entry_maryn.xml')
return abv-m:make-geomap($doc,'en') :)
(: PARSE CSV OF LANGNAMES. IF I WILL EVER NEED IT :)
(: let $text := file:read-text('./basex/webapp/csv/langnames.csv')
return db:put('abaevdict_index',
csv:parse($text, { 'header': true() }),
'langnames.xml') :)