diff --git a/.gitignore b/.gitignore index 16c31aef..ec6ca00a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ __pycache__/ # internal edoc/resources/xsl/xspec/ .existdb.json +edoc/rest2/v2.json # node-reladted stuff node_modules/ diff --git a/README.md b/README.md index a09379b8..30fc5d4d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,47 @@ This framework still lacks a good name. If you have an idea, please let me know! ## Incompatible changes +### 25Q3 + +Release 25Q3 dropped support for more unsued functions: +- `wdb:getFilePath ( $id as xs:string )`: use the map from `wdbFiles:getFullPath` instead +- the default layout of all `resources` collections has changed to group files by type. This also affects the main + project specific overrides, i.e. `project.js` and `project.css`. An XQuery is provided to move all files to their + appropriate new locations (TODO: add file name here). + This also affects `edoc/data/resources` and `edoc/resources` so you might have to change imports manually if you make + use of any file in these collections. + +Changes in standard behaviour +- sub-projects will now make use of process inheritance; i.e., they only define empty `processes` with no `command`. A + `command` is then picked by traversing up through parent `wdbmeta.xml` (i.e., one that is pointed to by a + `struct/import`; worst case: data). This way, you can still have different `command` defined for sub-projects (and + their children) but do not need to change the path for every sub-project. +- as part of this, no XSLTs are being copied to `{$subproject}/resources` as inheritance is now the standard. This way, + surplus XSLTs do not have to be deleted or kept up to date. As said above, it is still possible to create a `command` + for this sub-project tree and create specific XSLTs (usually by including the main XSLTs) +- standard XSLTs for a new project are now bare: they only include `/edoc/data/resources/xslt/{$currentFileName}`, and + `tei-common.xsl` (unless it’s common itself). + +### 24Q4 + +Release 24Q4 dropped another set of functions that were unused: +- `wdb:getEdFromFileID( $id as xs:string )`: `(wdbFiles:getFullPath($id))?projectPath` returns the base path to `wdbmeta.xml` +- `wdb:getMetaElementFromEd ( $ed as xs:string )`: use + `doc( (doc("/db/apps/edoc/index/project-index.xml")/id($ed))/@path || '/wdbmeta.xml' )/id($ed)[self::meta:projectMD]` instead +- `wdb:getMetaFile( $pathToEd )`: `(wdbFiles:getFullPath($ed))?projectPath` returns the base path to `wdbmeta.xml` +- `wdb:getProjectPathFromId ( $ed )`: use `(wdbFiles:getFullPath($ed))?projectPath` instead + +### 24Q2 + +Release 24Q2 dropped functions `wdb:getEdPath( $ed as xs:string , $absolute as xs:boolean() )`, +`wdb:getEdPath( $ed as xs:string )`, and `wdb:findProjectXQM( $project )`. These queries can be replaced by +`(wdbFiles:getFullPath($id))` which returns a map with `projectPath` (the path to the project, i.e. the collection where +`wdbmeta.xml`¹ is stored), `collectionPath` (for the subcollection where a file is actually located), `mainProject` for +the path to the project containing `project.xqm`, and `fileName`. +1) (24Q4): this corrects a typo as previous versions incorrectly read `project.xqm`. + +### 24Q1 + Release 24Q1 dropped support for METS-based projects. As METS files can have a number of very different ways of encoding information, especially when it comes to behaviours, native support is hard to achieve. At the same time, most installations use wdb+’s native wdbmeta system as this is what the admin functions work with. @@ -64,9 +105,11 @@ into `/db/apps/edoc` and want to put your projects into `/db/apps/edoc/data/your - - /db/apps/edoc/resources/xsl/tei-transcript.xsl - + + + /db/apps/edoc/resources/xsl/tei-transcript.xsl + + @@ -96,5 +139,12 @@ See the Wiki for details! * Akademie der Wissenschaften, Heidelberg * Theologenbriefwechsel * ULB Darmstadt + * TUEditions + * WDM If you use wdbplus for your editions, please drop me a message so I can add you to this list. + +## Sponsoring + +Development of wdb+ is chiefly done in projects funded by DFG and the German BMBF. +Additionally, we would like to say thank you to BrowserStack for giving us sponsored access! diff --git a/build.xml b/build.xml index d1a0ed34..40d61c3d 100644 --- a/build.xml +++ b/build.xml @@ -1,23 +1,25 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/edoc/admin/admin.xqm b/edoc/admin/admin.xqm index 7f9aaa44..e2feb608 100644 --- a/edoc/admin/admin.xqm +++ b/edoc/admin/admin.xqm @@ -2,73 +2,61 @@ xquery version "3.1"; module namespace wdbAdmin = "https://github.com/dariok/wdbplus/Admin"; -import module namespace console = "http://exist-db.org/xquery/console" at "java:org.exist.console.xquery.ConsoleModule"; -import module namespace templates = "http://exist-db.org/xquery/html-templating"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm"; -import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "/db/apps/edoc/modules/error.xqm"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "../modules/wdb-config.xqm"; +import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "../modules/error.xqm"; +import module namespace wdbm = "https://github.com/dariok/wdbplus/model" at "../modules/model.xqm"; -declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; -declare namespace sm = "http://exist-db.org/xquery/securitymanager"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace sm = "http://exist-db.org/xquery/securitymanager"; +declare namespace templates = "http://exist-db.org/xquery/html-templating"; +declare namespace wdb = "https://github.com/dariok/wdbplus/wdb"; (:~ - : populate the model for functions pages (similar but not identical to wdb:populateModel) + : populate the model for admin pages : : @param $ed The ID of a _project_ : @return The model :) declare - %templates:default("ed", "") -function wdbAdmin:start ( $node as node(), $model as map(*), $ed as xs:string ) { - try { - let $pathToEd := if ( $ed = "" ) - then $wdb:data - else wdb:getEdPath($ed, true()) - - (: The meta data are taken from wdbmeta.xml :) - let $infoFileLoc := wdb:getMetaFile($pathToEd) - , $title := normalize-space((doc($infoFileLoc)//meta:title)[1]) - - return map { - "ed": if ( $pathToEd = $wdb:data ) then "data" else $ed, - "infoFileLoc": $infoFileLoc, - "page": substring-after(request:get-uri(), "admin/"), - "pathToEd": $pathToEd, - "title": $title, - "auth": sm:id()/sm:id - } - } catch * { - util:log("error", "No collection found for project ID " || $ed), - map { - "ed": "" - } - } + %templates:default("ed", "data") +function wdbAdmin:start ( $node as node(), $model as map(*), $ed as xs:string ) as item()* { + wdbm:populateModel((), $ed, "", "", "") }; -declare function wdbAdmin:getEd ( $node as node(), $model as map(*) ) as element(meta) { - -}; +declare function wdbAdmin:getEd ( $node as node(), $model as map(*) ) as item()+ {( + comment { "Created in admin.xqm for "|| $node/@data-template }, + , + +)}; -declare function wdbAdmin:heading ($node as node(), $model as map(*)) { +declare function wdbAdmin:heading ( $node as node(), $model as map(*) ) as element()+ { let $opts := if (request:get-parameter('job', '') != '') then globale Optionen else () return ( +

{ - if ($model?page = 'admin.html') - then "Admin-Seite" - else if ($model?page = 'global.html') - then "Globale Einstellungen" - else if ($model?ed = '') - then "Projekte" - else ("Projekt ", {$model?title}, " (" || $model?ed || ")") + comment { "Created in admin.xqm for "|| $node/@data-template }, + if ($model?page = 'admin.html') then + "Admin-Seite" + else if ($model?page = 'global.html') then + "Globale Einstellungen" + else if ($model?ed = '') then + "Projekte" + else ( + "Projekt ", + {$model?title}, + " (" || $model?ed || ")" + ) }

, $opts ) }; -declare function wdbAdmin:getAside ($node as node(), $model as map(*)) as element() { +declare function wdbAdmin:getAside ( $node as node(), $model as map(*) ) as element() { }; -declare function wdbAdmin:css ( $node as node(), $model as map(*) ) as element()* { - if ( unparsed-text-available($wdb:data || "/resources/wdb.css") ) - then +declare function wdbAdmin:css ( $node as node(), $model as map(*) ) as item()* { + comment { "Created in admin.xqm for "|| $node/@data-template }, + if ( unparsed-text-available($config:data || "/resources/css/wdb.css") ) + then else (), - if ( unparsed-text-available($wdb:data || "/resources/admin.css") ) - then + if ( unparsed-text-available($config:data || "/resources/css/admin.css") ) + then else () }; diff --git a/edoc/admin/directoryForm.html b/edoc/admin/directoryForm.html index 61c9f547..47a138b1 100644 --- a/edoc/admin/directoryForm.html +++ b/edoc/admin/directoryForm.html @@ -1,29 +1,27 @@
-

Funktion

-
-
- Verzeichnis ohne Eintragen in wdbmeta
- Verzeichnis mit Eintragen in wdbmeta
- Datei(en) ohne Eintragen in wdbmeta
- Datei(en) mit Eintragen in wdbmeta
+

Funktion

+ +
+ Verzeichnis(se) (relative Pfade)
+ Datei(en)
-
- -
-      
- - -
-
- - -
- - -

- loading -

- +
+ +
+         
+ + +
+
+ + +
+ + +

+ loading +

+
diff --git a/edoc/admin/global.xqm b/edoc/admin/global.xqm index 1e759203..30a91cec 100644 --- a/edoc/admin/global.xqm +++ b/edoc/admin/global.xqm @@ -1,22 +1,19 @@ -xquery version "3.0"; +xquery version "3.1"; module namespace wdbGS = "https://github.com/dariok/wdbplus/GlobalSettings"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; -import module namespace console = "http://exist-db.org/xquery/console"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "../modules/wdb-config.xqm"; -declare namespace config = "https://github.com/dariok/wdbplus/config"; declare namespace exgit = "http://exist-db.org/xquery/exgit"; declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; declare namespace system = "http://exist-db.org/xquery/system"; -declare function wdbGS:getRest ( $node as node(), $model as map(*) ) { - +declare function wdbGS:getRest ( $node as node(), $model as map(*) ) as element(meta) { + }; declare function wdbGS:body ( $node as node(), $model as map(*) ) { let $param := request:get-parameter('job', 'main') - let $metaFile := doc('../config.xml') return switch ( $param ) case 'main' return @@ -32,24 +29,24 @@ declare function wdbGS:body ( $node as node(), $model as map(*) ) { case 'title' return - local:titleForm($metaFile) + local:titleForm($config:configFile) case 'chgTitle' return - let $u1 := update replace $metaFile//config:meta/config:name + let $u1 := update replace $config:configFile//config:meta/config:name with {request:get-parameter('longTitle', '')} - let $u1 := update replace $metaFile//config:meta/config:short + let $u1 := update replace $config:configFile//config:meta/config:short with {request:get-parameter('shortTitle', '')} - return local:titleForm($metaFile) + return local:titleForm($config:configFile) case 'role' return - local:roleForm($metaFile) + local:roleForm($config:configFile) case 'chgRole' return - let $u1 := update replace $metaFile//config:role/config:type + let $u1 := update replace $config:configFile//config:role/config:type with {request:get-parameter('role', '')} - let $u1 := update replace $metaFile//config:role/config:other + let $u1 := update replace $config:configFile//config:role/config:other with {request:get-parameter('other', '')} - return local:roleForm($metaFile) + return local:roleForm($config:configFile) default return
@@ -58,23 +55,23 @@ declare function wdbGS:body ( $node as node(), $model as map(*) ) {
}; -declare function local:titleForm($metaFile) { +declare function local:titleForm($config:configFile) {

Titeldaten verändern


+ value="{$config:configFile//config:meta/config:name}" />

+ value="{$config:configFile//config:meta/config:short}" />
}; -declare function local:roleForm($metaFile) { - let $role := $metaFile//config:role/config:type - let $other := $metaFile//config:role/config:other +declare function local:roleForm($config:configFile) { + let $role := $config:configFile//config:role/config:type + let $other := $config:configFile//config:role/config:other return
@@ -85,7 +82,7 @@ declare function local:roleForm($metaFile) {

@@ -95,5 +92,5 @@ declare function local:roleForm($metaFile) { }; declare function wdbGS:ingest($node as node(), $model as map(*)) { - bestehendes Projekt hochladen -}; \ No newline at end of file + bestehendes Projekt hochladen +}; diff --git a/edoc/admin/modelFunctions.xql b/edoc/admin/modelFunctions.xql index a7cd83b4..75d05bd2 100644 --- a/edoc/admin/modelFunctions.xql +++ b/edoc/admin/modelFunctions.xql @@ -2,6 +2,9 @@ xquery version "3.1"; module namespace trigger="http://exist-db.org/xquery/trigger"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace index = "https://github.com/dariok/wdbplus/index"; + declare function trigger:after-update-document ( $uri as xs:anyURI ) as xs:string { if ( ends-with($uri, 'instance.xqm') or ends-with($uri, 'project.xqm') ) then let $projectPath := if ( ends-with($uri, 'instance.xqm') ) @@ -12,5 +15,59 @@ declare function trigger:after-update-document ( $uri as xs:anyURI ) as xs:strin else 'project-functions.xml' return xmldb:store($projectPath, $statFileName, inspect:inspect-module($uri)) + else if ( ends-with($uri, 'wdbmeta.xml') ) then + let $meta := doc($uri) + , $projectId := $meta/meta:projectMD/@xml:id + , $files := $meta//meta:file + , $title := $meta//meta:title[@type='main'] + , $projectIndex := doc("/db/apps/edoc/index/project-index.xml") + , $fileIndex := doc("/db/apps/edoc/index/file-index.xml") + , $projectEntry := + + (: enter or update project :) + let $insertProject := if ( exists($projectIndex/id($projectId)) ) + then update replace $projectIndex/id($projectId) with $projectEntry + else update insert $projectEntry into $projectIndex/index:index + + (: enter or update files entries :) + let $entries := for $file in $files + let $id := $file/@xml:id + , $entry := + + return if ( exists($fileIndex/id($id)) ) + then update replace $fileIndex/id($id) with $entry + else update insert $entry into $fileIndex/index:index + + (: enter or update subcorpora :) + let $subcorpora := for $subcorpus in $meta//meta:struct[@xml:id] + let $id := $subcorpus/@xml:id + , $entry := + + return if ( exists($fileIndex/id($id)) ) + then update replace $fileIndex/id($id) with $entry + else update insert $entry into $fileIndex/index:index + + return $uri + (: else if ( ends-with($uri, '.xml') ) then + let $id := doc($uri)/*/@xml:id + , $present := doc("/db/apps/edoc/index/file-index.xml")/id($id) + , $entry := + , $insert := if ( $present ) + then update replace $present with $entry + else update insert $entry into doc("/db/apps/edoc/index/file-index.xml")/* + return $uri :) else "" }; diff --git a/edoc/admin/new.xqm b/edoc/admin/new.xqm index 540770d6..99b27f7b 100644 --- a/edoc/admin/new.xqm +++ b/edoc/admin/new.xqm @@ -1,108 +1,48 @@ -xquery version "3.0"; +xquery version "3.1"; module namespace wdbPN = "https://github.com/dariok/wdbplus/ProjectNew"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm"; -import module namespace wdbRc = "https://github.com/dariok/wdbplus/RestCollections" at "/db/apps/edoc/rest/rest-coll.xql"; -import module namespace sm = "http://exist-db.org/xquery/securitymanager"; +import module namespace sm = "http://exist-db.org/xquery/securitymanager"; -declare namespace config = "https://github.com/dariok/wdbplus/config"; -declare namespace http = "http://expath.org/ns/http-client"; -declare namespace map = "http://www.w3.org/2005/xpath-functions/map"; -declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; -declare namespace tei = "http://www.tei-c.org/ns/1.0"; +declare namespace http = "http://expath.org/ns/http-client"; +declare namespace map = "http://www.w3.org/2005/xpath-functions/map"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace tei = "http://www.tei-c.org/ns/1.0"; declare function wdbPN:body ( $node as node(), $model as map(*), $pName as xs:string*, $pShort as xs:string*, - $pID as xs:string*, $pColl as xs:string*, $pDate as xs:string*, $pDesc as xs:string*, $pLic as xs:string* ) { - let $user := sm:id() - - return if (not($user//sm:group = 'dba')) + $pID as xs:string*, $collection as xs:string* ) + (:), $pDate as xs:string*, $pDesc as xs:string*, $pLic as xs:string*, $data as xs:string* ) to be implemented later when a UI for project MD exists :) + as element() { + if ( not(sm:id()//sm:group = 'dba') ) then

Diese Seite ist nur für Administratoren zugänglich!

- else if (0 = (string-length($pName), string-length($pID), string-length($pColl))) + else if (0 = (string-length($pName), string-length($pID), string-length($collection))) then -
-
-
-
-
-
+ +
+
+
+
+ + else - let $collectionData := - - {$pName} - {$pID} - {$pColl} - - - let $targetCollection := if ( $model?ed eq '' ) then 'data' else $model?ed - , $create := wdbRc:createSubcollectionXml ($collectionData, $targetCollection) - - return if ( ($create)[1]//http:response/@status = '201') - then - let $collection-uri := $create[2] - let $textCollection := xmldb:create-collection($collection-uri, "texts") - let $resourcesCollection := xmldb:create-collection($collection-uri, "resources") - let $metaFile := $collection-uri || "/wdbmeta.xml" - - let $copy := if (system:function-available(xs:QName("xmldb:copy-collection"), 2)) - then util:eval("xmldb:copy-collection($source, $destination)", false(), ( - xs:QName("source"), $wdb:edocBaseDB || "/resources/xsl", - xs:QName("destination"), $collection-uri - )) - else util:eval("xmldb:copy($source, $destination)", false(), ( - xs:QName("source"), $wdb:edocBaseDB || "/resources/xsl", - xs:QName("destination"), $collection-uri - )) - - let $chmod := ( - sm:chmod(xs:anyURI($collection-uri), 'rwxrwxr-x'), - sm:chmod(xs:anyURI($textCollection), 'rwxrwxr-x'), - sm:chmod(xs:anyURI($resourcesCollection), 'rwxrwxr-x'), - sm:chmod(xs:anyURI($metaFile), 'rw-rw-r--'), - sm:chmod(xs:anyURI($collection-uri || "/xsl"), "rwxrwxr-x"), - sm:chown(xs:anyURI($collection-uri), "wdb:wdbusers"), - sm:chown(xs:anyURI($textCollection), "wdb:wdbusers"), - sm:chown(xs:anyURI($resourcesCollection), "wdb:wdbusers"), - sm:chown(xs:anyURI($metaFile), "wdb:wdbusers"), - sm:chown(xs:anyURI($collection-uri || "/xsl"), "wdb:wdbusers"), - for $f in xmldb:get-child-resources($collection-uri || "/xsl") - return ( - sm:chmod(xs:anyURI($collection-uri || "/xsl/" || $f), "rwxrwxr-x"), - sm:chown(xs:anyURI($collection-uri || "/xsl/" || $f), "wdb:wdbusers") - ) - ) - - let $MD := doc($metaFile) - let $addMD := ( - if ($pShort != "") - then - update insert {$pShort} into $MD//meta:titleData - else (), - if ($pDate != "") - then - update insert {$pDate} into $MD//meta:titleData - else (), - if ($pLic != "") - then - update insert {$pLic} into $MD//meta:legal - else () - ) - - return -
-
Collection
-
{$create[2]}
-
wdbmeta.xml:
-
{$metaFile}
-
Admin
-
Upload
-
- else $create +
+
Collection
+
{ $collection }
+
Name
+
{ $pName }
+
Short title
+
{ $pShort }
+
Admin
+
+ +
+
}; diff --git a/edoc/admin/project-template/project.xqm b/edoc/admin/project-template/project.xqm new file mode 100644 index 00000000..4b869cb3 --- /dev/null +++ b/edoc/admin/project-template/project.xqm @@ -0,0 +1,5 @@ +xquery version "3.1"; + +module namespace wdbPF = "https://github.com/dariok/wdbplus/projectFiles"; + +declare namespace tei = "http://www.tei-c.org/ns/1.0"; \ No newline at end of file diff --git a/edoc/admin/project-template/resources/xsl/tei-common.xsl b/edoc/admin/project-template/resources/xsl/tei-common.xsl new file mode 100644 index 00000000..c2ae9bdb --- /dev/null +++ b/edoc/admin/project-template/resources/xsl/tei-common.xsl @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/edoc/admin/project-template/resources/xsl/tei-transcript.xsl b/edoc/admin/project-template/resources/xsl/tei-transcript.xsl new file mode 100644 index 00000000..3c7883c4 --- /dev/null +++ b/edoc/admin/project-template/resources/xsl/tei-transcript.xsl @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/edoc/admin/project-template/wdbmeta.xml b/edoc/admin/project-template/wdbmeta.xml new file mode 100644 index 00000000..06f46d70 --- /dev/null +++ b/edoc/admin/project-template/wdbmeta.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + full text of transcribed sources + + + + + + + (no licence stated) + + + + + + resources/xsl/tei-transcript.xsl + + + + + + \ No newline at end of file diff --git a/edoc/admin/projects.xqm b/edoc/admin/projects.xqm index 0400a10f..020eec30 100644 --- a/edoc/admin/projects.xqm +++ b/edoc/admin/projects.xqm @@ -1,20 +1,18 @@ -xquery version "3.0"; +xquery version "3.1"; module namespace wdbPL = "https://github.com/dariok/wdbplus/ProjectList"; -import module namespace sm = "http://exist-db.org/xquery/securitymanager"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; -import module namespace wdbs = "https://github.com/dariok/wdbplus/stats" at "../modules/stats.xqm"; -import module namespace xstring = "https://github.com/dariok/XStringUtils" at "../include/xstring/string-pack.xql"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "../modules/wdb-config.xqm"; +import module namespace sm = "http://exist-db.org/xquery/securitymanager"; +import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "../modules/wdb-files.xqm"; +import module namespace wdbs = "https://github.com/dariok/wdbplus/stats" at "../modules/stats.xqm"; +import module namespace xstring = "https://github.com/dariok/XStringUtils" at "../include/xstring/string-pack.xql"; -declare namespace config = "https://github.com/dariok/wdbplus/config"; declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; declare namespace tei = "http://www.tei-c.org/ns/1.0"; -declare function wdbPL:pageTitle ($node as node(), $model as map(*)) { - let $t := $wdb:configFile//config:short - - return {normalize-space($t)} – Admin +declare function wdbPL:pageTitle ( $node as node(), $model as map(*) ) as element(title) { + { normalize-space($config:configFile//config:short) } – Admin }; declare function wdbPL:body ( $node as node(), $model as map(*) ) { @@ -39,38 +37,38 @@ declare function wdbPL:body ( $node as node(), $model as map(*) ) { return switch ($job) case 'add' return let $ins := let $up1 := update insert $ins into $metaFile//meta:files - return local:getFileStat($model , $file) + return wdbPL:getFileStat($model , $file) case 'uuid' return let $ins := attribute uuid {util:uuid($xml)} let $up1 := if ($fileEntry/@uuid) then update replace $fileEntry/@uuid with $ins else update insert $ins into $fileEntry - return local:getFileStat($model, $file) + return wdbPL:getFileStat($model, $file) case 'pid' return let $ins := attribute pid { string($xml//tei:publicationStmt/tei:idno[@type = 'URI']) } let $up1 := if ($fileEntry/@pid) then update replace $fileEntry/@pid with $ins else update insert $ins into $fileEntry - return local:getFileStat($model, $file) + return wdbPL:getFileStat($model, $file) case 'date' return let $ins := attribute date {xmldb:last-modified($subColl, $resource)} let $up1 := if ($fileEntry/@date) then update replace $fileEntry/@date with $ins else update insert $ins into $fileEntry - return local:getFileStat($model, $file) + return wdbPL:getFileStat($model, $file) case 'id' return let $ins := attribute xml:id {normalize-space($xml/tei:TEI/@xml:id)} let $upd1 := if ($fileEntry/@xml:id) then update replace $fileEntry/@xml:id with $ins else update insert $ins/@xml:id into $fileEntry - return local:getFileStat($model, $file) + return wdbPL:getFileStat($model, $file) case 'private' return let $id := normalize-space($xml/tei:TEI/@xml:id) @@ -80,7 +78,7 @@ declare function wdbPL:body ( $node as node(), $model as map(*) ) { else if ($view/@private = 'false') then update value $view/@private with 'true' else update insert attribute private {'true'} into $view - return local:getFileStat($model, $file) + return wdbPL:getFileStat($model, $file) default return

Strange Error

@@ -92,7 +90,7 @@ declare function wdbPL:body ( $node as node(), $model as map(*) ) { else if ($model?ed != 'data' and $model?ed != ''and $file = '') then local:getFiles($model) else - local:getFileStat($model, $file) + wdbPL:getFileStat($model, $file) }; declare function local:getFiles($model) { @@ -136,7 +134,7 @@ declare function local:getFiles($model) { {substring($info[4], 1, 100)} -
+ } @@ -144,20 +142,20 @@ declare function local:getFiles($model) { }; -declare function local:getFileStat($model, $file) { - let $filePath := wdb:getFilePath($file) - let $doc := doc($filePath) - let $metaFile := doc($model?infoFileLoc) - let $entry := $metaFile/id($file) - let $uuid := util:uuid($doc) - let $pid := $entry/@pid - let $date := xmldb:last-modified(xstring:substring-before-last($filePath, "/"), - xstring:substring-after-last($filePath, "/")) +declare %private function wdbPL:getFileStat( $model as map(*), $id as xs:string ) as element(div) { + let $fullPath := wdbFiles:getFullPath($id) + , $filePath := $fullPath?collectionPath || "/" || $fullPath?fileName + , $doc := doc($filePath) + , $metaFile := doc($fullPath?projectPath || "/wdbmeta.xml") + , $entry := $metaFile/id($id) + , $uuid := util:uuid($doc) + , $pid := $entry/@pid + , $date := xmldb:last-modified($fullPath?collectionPath, $fullPath?fileName) return
-

{$file}

+

{ $id }


anzeigenanzeigen
@@ -189,7 +187,7 @@ declare function local:getFileStat($model, $file) { {if ($entry/@path != '') then - else + else } {if ($entry/@path != '') @@ -198,28 +196,28 @@ declare function local:getFileStat($model, $file) { {if ($entry/@uuid = $uuid) then - else + else } , , {if ($entry/@date = $date) then - else + else } , {if ($entry/@xml:id = $doc/tei:TEI/@xml:id) then - else + else } ) @@ -228,8 +226,8 @@ declare function local:getFileStat($model, $file) {
Eintrag in wdbmeta.xml vorhanden?OKfehlt hinzufügenfehlt hinzufügen
UUID in wdbMetaOK: {$uuid}{normalize-space($entry/@uuid)}
UUID aktualisieren
{normalize-space($entry/@uuid)}
UUID aktualisieren
externe PID {if ($entry/@pid = $pid) then "OK: " || string($entry/@pid) - else PID aus Datei übernehmen + else PID aus Datei übernehmen }
Timestamp in wdbMetaOK: {$date}{normalize-space($entry/@date)}
Timestamp aktualisieren
{normalize-space($entry/@date)}
Timestamp aktualisieren
@xml:id in wdbMetaOK: {$entry/@xml:id/string()}{normalize-space($entry/@xml:id)}
ID aktualisieren
{normalize-space($entry/@xml:id)}
ID aktualisieren
{ - if ($wdb:role = 'workbench') then - let $remoteMetaFilePath := $wdb:peer || '/' || substring-after($model?pathToEd, $wdb:data) || '/wdbmeta.xml' + (: if ( $config:role = 'workbench' ) then + let $remoteMetaFilePath := $config:peer || '/' || substring-after($model?pathToEd, $config:data) || '/wdbmeta.xml' let $remoteMetaFile := try { doc($remoteMetaFilePath) } catch * { @@ -238,7 +236,7 @@ declare function local:getFileStat($model, $file) { c: ' || $err:value || ' in ' || $err:module || ' a: ' || $err:additional) } - let $remoteEntry := $remoteMetaFile//meta:file[@xml:id = $file] + let $remoteEntry := $remoteMetaFile//meta:file[@xml:id = $id] return (

Peer Info

, @@ -246,7 +244,7 @@ declare function local:getFileStat($model, $file) { Peer Server - {$wdb:peer} + { $config:peer } Eintrag in wdbmeta.xml vorhanden? @@ -273,8 +271,8 @@ declare function local:getFileStat($model, $file) { , @xml:id in wdbMeta - {if ($remoteEntry/@xml:id = $file) - then OK: {$file} + {if ($remoteEntry/@xml:id = $id) + then OK: { $id } else Diff: {normalize-space($remoteEntry/@xml:id)} } @@ -284,13 +282,13 @@ declare function local:getFileStat($model, $file) { ) - else () + else () :) } { - if ($wdb:role = 'standalone') then - let $status := if ($metaFile//meta:view[@file = $file]) + if ( $config:role = 'standalone' ) then + let $status := if ($metaFile//meta:view[@file = $id]) then - let $view := ($metaFile//meta:view[@file = $file])[1] + let $view := ($metaFile//meta:view[@file = $id])[1] return if ($view/@private = true()) then 'intern' else 'sichtbar' @@ -305,7 +303,7 @@ declare function local:getFileStat($model, $file) { if ($status = 'Kein Struktureintrag') then $status else - let $link := umschalten + let $link := umschalten return ($status,
, $link) } @@ -316,4 +314,4 @@ declare function local:getFileStat($model, $file) { }
-}; \ No newline at end of file +}; diff --git a/edoc/admin/transform-test.xql b/edoc/admin/transform-test.xql deleted file mode 100644 index 9bbecb62..00000000 --- a/edoc/admin/transform-test.xql +++ /dev/null @@ -1,40 +0,0 @@ -xquery version "3.1"; - -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "modules/app.xql"; - -let $id := "edoc_wd_1703-08-20" - -let $model := wdb:populateModel($id, "", map{}) - - let $file := $model("fileLoc") - let $xslt := $model("xslt") - let $params := - - - - - - { - if ($model("view") != '') - then - else () - } - - (: ambiguous rule match soll nicht zum Abbruch führen :) - let $attr := - - let $re := - try { transform:transform(doc($file), doc($xslt), $params, $attr, "expand-xincludes=no") } - catch * { - - {$file} - {$xslt} - {$params} - {$attr} - {$err:code || ': ' || $err:description} - {$err:module || '@' || $err:line-number ||':'||$err:column-number} - {$err:additional} - - } - -return ($model, $re) \ No newline at end of file diff --git a/edoc/admin/view.xql b/edoc/admin/view.xql index 211c57b4..09eedc4b 100644 --- a/edoc/admin/view.xql +++ b/edoc/admin/view.xql @@ -7,7 +7,6 @@ xquery version "3.1"; declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; -import module namespace config = "http://exist-db.org/xquery/apps/config" at "../modules/config.xqm"; import module namespace templates = "http://exist-db.org/xquery/html-templating"; import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; import module namespace wdbAdmin = "https://github.com/dariok/wdbplus/Admin" at "admin.xqm"; @@ -24,8 +23,9 @@ declare option output:media-type "text/html"; : The following modules provide functions which will be called by the : templating. :) +let $app-root := "/db/" || substring-after(system:get-module-load-path(), "/db/") => substring-before("admin") let $config := map { - $templates:CONFIG_APP_ROOT: $config:app-root, + $templates:CONFIG_APP_ROOT: $app-root, $templates:CONFIG_STOP_ON_ERROR: true() } diff --git a/edoc/config.xml b/edoc/config.xml index 9570ec01..ed17041e 100644 --- a/edoc/config.xml +++ b/edoc/config.xml @@ -28,7 +28,8 @@ http://localhost:8080/exist/apps/edoc - http://localhost:8080/exist/restxq/edoc/ + http://localhost:8080/exist/restxq/edoc/ + https://localhost/exist/apps/edoc/api/v2/ @@ -36,11 +37,24 @@ +
-
+
+
- + + + diff --git a/edoc/config/edoc/data/collection.xconf b/edoc/config/edoc/data/collection.xconf index 503ecb9a..0a993258 100644 --- a/edoc/config/edoc/data/collection.xconf +++ b/edoc/config/edoc/data/collection.xconf @@ -10,7 +10,6 @@ - @@ -18,6 +17,7 @@ + @@ -41,10 +41,7 @@ - - - - + @@ -77,6 +74,8 @@ + + diff --git a/edoc/config/edoc/data/documentation/collection.xconf b/edoc/config/edoc/data/documentation/collection.xconf new file mode 100644 index 00000000..56fb2470 --- /dev/null +++ b/edoc/config/edoc/data/documentation/collection.xconf @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/edoc/controller.xql b/edoc/controller.xql index f39f39e8..3a974fc5 100644 --- a/edoc/controller.xql +++ b/edoc/controller.xql @@ -5,69 +5,58 @@ :) xquery version "3.1"; -import module namespace config = "http://exist-db.org/xquery/apps/config" at "/db/apps/eXide/modules/config.xqm"; -import module namespace login = "http://exist-db.org/xquery/login" at "resource:org/exist/xquery/modules/persistentlogin/login.xql"; -import module namespace request = "http://exist-db.org/xquery/request" at "java:org.exist.xquery.functions.request.RequestModule"; -import module namespace sm = "http://exist-db.org/xquery/securitymanager" at "java:org.exist.xquery.functions.securitymanager.SecurityManagerModule"; -import module namespace wdba = "https://github.com/dariok/wdbplus/auth" at "/db/apps/edoc/modules/auth.xqm"; +import module namespace login = "http://exist-db.org/xquery/login" at "resource:org/exist/xquery/modules/persistentlogin/login.xql"; +import module namespace request = "http://exist-db.org/xquery/request" at "java:org.exist.xquery.functions.request.RequestModule"; -declare namespace exist = "http://exist.sourceforge.net/NS/exist"; +declare namespace config = "https://github.com/dariok/wdbplus/config"; +declare namespace exist = "http://exist.sourceforge.net/NS/exist"; declare variable $exist:path external; declare variable $exist:resource external; declare variable $exist:controller external; declare variable $exist:prefix external; -declare variable $exist:root external; +(: declare variable $exist:root external; :) -(: von eXide geklaut :) -declare function local:user-allowed() { - ( - request:get-attribute("wd.user") and - request:get-attribute("wd.user") != "guest" - ) or config:get-configuration()/restrictions/@guest = "yes" -}; -declare function local:query-execution-allowed() { - ( - config:get-configuration()/restrictions/@execute-query = "yes" - and local:user-allowed() - ) - or sm:is-dba((request:get-attribute("wd.user"),request:get-attribute("xquery.user"), 'nobody')[1]) -}; +declare variable $local:isget := request:get-method() = ("GET","get"); +declare variable $local:config := doc("/db/apps/edoc/config.xml")/config:config; -let $cookiePath := substring-before(request:get-uri(), $exist:path) - , $duration := xs:dayTimeDuration("P2D") +util:log("info", request:get-method() || " " || request:get-url() || ' ? ' || request:get-query-string() || " -> resource: " || $exist:resource), -return -if ( $exist:resource eq '' or $exist:resource eq 'index.html' ) then - - - +(: static HTML page for API documentation should be served directly to make sure it is always accessible :) +if ( + ( $local:isget and $exist:resource = ('v2.json', 'apiv2.html') ) +) then + + + (: login :) else if ( $exist:resource = 'login' ) then - ( - login:set-user("wd", $cookiePath, $duration, false()), - try { - if (request:get-parameter('logout', '') = 'logout') then - wdba:getAuth(
, map {'res': 'logout'}) - else if (local:user-allowed()) then - wdba:getAuth(
, map {'auth': {request:get-attribute("wd.user")}}) - else ( - response:set-status-code(401), - fail - ) - } catch * { - response:set-status-code(403), - {$err:description} - } - ) + + + +(: logout :) +else if ( $exist:resource = 'logout' ) then + + + + + +(: REST API :) +else if ( contains($exist:path, 'api/v2') ) then + + + +else if ( $exist:resource eq '' or $exist:resource eq 'index.html' ) then + + + (: admin pages :) else if ( ends-with($exist:resource, ".html") and contains($exist:path, '/admin/') ) then - { login:set-user("wd", $cookiePath, $duration, false()) } + { login:set-user("wd", substring-before(request:get-uri(), $exist:path), xs:dayTimeDuration("P2D"), false()) } - { login:set-user("wd", $cookiePath, $duration, false()) } @@ -80,23 +69,35 @@ else if ( ends-with($exist:resource, ".html") ) then - { login:set-user("wd", $cookiePath, $duration, false()) } - + { + for $header in $local:config//config:header + return { $header/@* } + } + - - - - - -else if ( contains($exist:path, "/$shared/") ) then - - - - + (: generic resources :) + else if ( contains($exist:path, "/$shared/") ) then + + + { + for $header in $local:config//config:header + return { $header/@* } + } + + + (: instance specific resources :) + else if ( contains($exist:path, "/$global/") ) then + + + { + for $header in $local:config//config:header + return { $header/@* } + } + + else if ( ends-with($exist:path, ".xql") ) then - { login:set-user("wd", $cookiePath, $duration, false()) } diff --git a/edoc/data/documentation/project.xqm b/edoc/data/documentation/project.xqm new file mode 100644 index 00000000..4b869cb3 --- /dev/null +++ b/edoc/data/documentation/project.xqm @@ -0,0 +1,5 @@ +xquery version "3.1"; + +module namespace wdbPF = "https://github.com/dariok/wdbplus/projectFiles"; + +declare namespace tei = "http://www.tei-c.org/ns/1.0"; \ No newline at end of file diff --git a/edoc/data/documentation/resources/xsl/tei-common.xsl b/edoc/data/documentation/resources/xsl/tei-common.xsl new file mode 100644 index 00000000..c2ae9bdb --- /dev/null +++ b/edoc/data/documentation/resources/xsl/tei-common.xsl @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/edoc/data/documentation/resources/xsl/tei-transcript.xsl b/edoc/data/documentation/resources/xsl/tei-transcript.xsl new file mode 100644 index 00000000..3c7883c4 --- /dev/null +++ b/edoc/data/documentation/resources/xsl/tei-transcript.xsl @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/edoc/data/documentation/wdbmeta.xml b/edoc/data/documentation/wdbmeta.xml new file mode 100644 index 00000000..e3f88a27 --- /dev/null +++ b/edoc/data/documentation/wdbmeta.xml @@ -0,0 +1,47 @@ + + + + + wdb+ Documentation + + + + + + + + + + + + + + + + docu + + + + + + full text of transcribed sources + + + + + + + (no licence stated) + + + + + + resources/xsl/tei-transcript.xsl + + + + + + \ No newline at end of file diff --git a/edoc/data/instance.xqm b/edoc/data/instance.xqm index 3b80af62..85ef0bc4 100644 --- a/edoc/data/instance.xqm +++ b/edoc/data/instance.xqm @@ -6,4 +6,4 @@ declare namespace tei = "http://www.tei-c.org/ns/1.0"; declare function wdbPF:getInstanceName () as xs:string { doc('wdbmeta.xml')//*:title[1] -}; \ No newline at end of file +}; diff --git a/edoc/data/resources/blobs/.gitkeep b/edoc/data/resources/blobs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/css/.gitkeep b/edoc/data/resources/css/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/html/.gitkeep b/edoc/data/resources/html/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/images/.gitkeep b/edoc/data/resources/images/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/js/.gitkeep b/edoc/data/resources/js/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/xq/.gitkeep b/edoc/data/resources/xq/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/data/resources/xsl/tei-common.xsl b/edoc/data/resources/xsl/tei-common.xsl new file mode 100644 index 00000000..c2ae9bdb --- /dev/null +++ b/edoc/data/resources/xsl/tei-common.xsl @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/edoc/data/resources/xsl/tei-transcript.xsl b/edoc/data/resources/xsl/tei-transcript.xsl new file mode 100644 index 00000000..3c7883c4 --- /dev/null +++ b/edoc/data/resources/xsl/tei-transcript.xsl @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/edoc/data/wdbmeta.xml b/edoc/data/wdbmeta.xml index e6f1825c..ca2cd1d0 100644 --- a/edoc/data/wdbmeta.xml +++ b/edoc/data/wdbmeta.xml @@ -2,7 +2,7 @@ - + wdb+ main project collection @@ -22,8 +22,10 @@ - - - + + + + + - \ No newline at end of file + diff --git a/edoc/doc/Dokumentation.xml b/edoc/doc/Dokumentation.xml index 7a34a861..e073932a 100644 --- a/edoc/doc/Dokumentation.xml +++ b/edoc/doc/Dokumentation.xml @@ -61,7 +61,7 @@ Where to find the function

the files can be found in /edoc/modules/start.xqm - /edoc/resources/start.xsl + /edoc/resources/xsl/start.xsl

The start.xqm @@ -79,7 +79,7 @@
If you want to change it on a project-level: link to - project/resource/startLeft.html and startRight.html; if you want to change it + {$project}/resource/html/startLeft.html and {$project}/resource/html/startRight.html; if you want to change it globally, you can override the default behaviour by changing edoc/data/instance.xqm

diff --git a/edoc/doc/outline-view.html b/edoc/doc/outline-view.html index a4447d58..af600f75 100644 --- a/edoc/doc/outline-view.html +++ b/edoc/doc/outline-view.html @@ -40,7 +40,7 @@

...

-
+
diff --git a/edoc/doc/wdbadmin_object.dita b/edoc/doc/wdbadmin_object.dita index 0466cf58..c5ea4733 100644 --- a/edoc/doc/wdbadmin_object.dita +++ b/edoc/doc/wdbadmin_object.dita @@ -9,10 +9,6 @@ displayRight(url) get info from URL and display it on the right - - showFile(ed, file) - Show file information on the right - showJob(job, file) Show job results diff --git a/edoc/expath-pkg.xml b/edoc/expath-pkg.xml index fe43428b..a643779e 100644 --- a/edoc/expath-pkg.xml +++ b/edoc/expath-pkg.xml @@ -1,4 +1,6 @@ - + W. Digitale Bibliothek + + diff --git a/edoc/include/xstring b/edoc/include/xstring index 375c9791..161fa524 160000 --- a/edoc/include/xstring +++ b/edoc/include/xstring @@ -1 +1 @@ -Subproject commit 375c97910f230dd01ad0d65a7e25ff0bfa945dd3 +Subproject commit 161fa52464122bff89c45f2b467ebb9383d00431 diff --git a/edoc/index/file-index.xml b/edoc/index/file-index.xml new file mode 100644 index 00000000..edc5cd73 --- /dev/null +++ b/edoc/index/file-index.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/edoc/index/index-projects.xq b/edoc/index/index-projects.xq new file mode 100644 index 00000000..693cd545 --- /dev/null +++ b/edoc/index/index-projects.xq @@ -0,0 +1,26 @@ +xquery version "3.1"; + +declare namespace index = "https://github.com/dariok/wdbplus/index"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; + +update delete doc("/db/apps/edoc/index/project-index.xml")/index:index/*, +update delete doc("/db/apps/edoc/index/file-index.xml")/index:index/*, +for $project in collection('/db/apps/edoc/data')//meta:projectMD + let $path := util:collection-name($project) + let $files := $project//meta:file + let $file-entries := for $file in $files + return + + return ( + update insert into doc("/db/apps/edoc/index/project-index.xml")/index:index, + if ( not(empty($file-entries)) ) + then update insert $file-entries into doc("/db/apps/edoc/index/file-index.xml")/index:index + else () + ) diff --git a/edoc/index/project-index.xml b/edoc/index/project-index.xml new file mode 100644 index 00000000..40982b50 --- /dev/null +++ b/edoc/index/project-index.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/edoc/logs/errors.xml b/edoc/logs/errors.xml new file mode 100644 index 00000000..ff5db007 --- /dev/null +++ b/edoc/logs/errors.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/edoc/modules/addin.xqm b/edoc/modules/addin.xqm index 606dc0fe..6098d724 100644 --- a/edoc/modules/addin.xqm +++ b/edoc/modules/addin.xqm @@ -5,15 +5,15 @@ xquery version "3.1"; module namespace wdbAddinMain = "https://github.com/dariok/wdbplus/addins-main"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm"; -import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "error.xqm"; +import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "error.xqm"; +declare namespace request = "http://exist-db.org/xquery/request"; declare namespace wdbadd = "https://github.com/dariok/wdbplus/addins"; (: load the main XQuery module for the requested addin. It is mandatory these implement wdbadd:main($map as map(*)) :) declare function wdbAddinMain:body ( $node as node(), $model as map(*) ) as element()+ { let $addinName := substring-before(substring-after(request:get-uri(), 'addins/'), '/') - , $path := $wdb:edocBaseDB || "/addins/" || $addinName || "/addin.xqm" + , $path := "/db/apps/edoc/addins/" || $addinName || "/addin.xqm" , $map := map { "location-hints": $path } let $module := try { diff --git a/edoc/modules/annotations.xqm b/edoc/modules/annotations.xqm index 71b6b32e..e6a9592c 100644 --- a/edoc/modules/annotations.xqm +++ b/edoc/modules/annotations.xqm @@ -2,7 +2,9 @@ xquery version "3.1"; module namespace wdbanno = "https://github.com/dariok/wdbplus/anno"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "wdb-config.xqm"; + +declare namespace xmldb = "http://exist-db.org/xquery/xmldb"; (:~ : return the annotation file for the given user on the given file. @@ -13,8 +15,8 @@ import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xq : @return node(): the annotation file :) declare function wdbanno:getAnnoFile($file as xs:anyURI, $username as xs:string) as node() { - let $annotationCollectionName := substring-before(substring-after($file, $wdb:data), '.xml') - let $annotationCollectionBase := $wdb:edocBaseDB || '/annotations/' + let $annotationCollectionName := substring-before(substring-after($file, $config:data), '.xml') + let $annotationCollectionBase := $config:edocBaseDB || '/annotations/' let $annotationCollection := if (xmldb:collection-available($annotationCollectionBase || $annotationCollectionName)) then $annotationCollectionBase || $annotationCollectionName else if (sm:has-access($annotationCollectionBase, 'w')) diff --git a/edoc/modules/app.xqm b/edoc/modules/app.xqm index 3f191fd6..0394c3e9 100644 --- a/edoc/modules/app.xqm +++ b/edoc/modules/app.xqm @@ -11,93 +11,16 @@ xquery version "3.1"; module namespace wdb = "https://github.com/dariok/wdbplus/wdb"; -import module namespace templates = "http://exist-db.org/xquery/html-templating"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "wdb-config.xqm"; import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "error.xqm"; import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "wdb-files.xqm"; -import module namespace wdbPF = "https://github.com/dariok/wdbplus/projectFiles" at "/db/apps/edoc/data/instance.xqm"; -import module namespace xConf = "http://exist-db.org/xquery/apps/config" at "config.xqm"; +import module namespace wdbPF = "https://github.com/dariok/wdbplus/projectFiles" at "../data/instance.xqm"; import module namespace xstring = "https://github.com/dariok/XStringUtils" at "../include/xstring/string-pack.xql"; -declare namespace config = "https://github.com/dariok/wdbplus/config"; -declare namespace main = "https://github.com/dariok/wdbplus"; -declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; -declare namespace rest = "http://exquery.org/ns/restxq"; -declare namespace tei = "http://www.tei-c.org/ns/1.0"; - -(: ALL-PURPOSE VARIABLES :) -(:~ - : load the config file - : See https://github.com/dariok/wdbplus/wiki/Global-Configuration - :) -declare variable $wdb:configFile := doc('../config.xml'); - -(:~ - : the base of this instance within the db - :) -declare variable $wdb:edocBaseDB := $wdb:configFile => base-uri() => substring-before('/config.xml'); - -(:~ - : Try to get the data collection. Documentation explicitly tells users to have a wdbmeta.xml - : in the Collection that contains all projects - :) -declare variable $wdb:data := - if ($wdb:configFile//config:data) - then normalize-space($wdb:configFile//config:data) - else - let $editionsW := collection($wdb:edocBaseDB)//meta:projectMD - - let $paths := for $f in $editionsW - let $path := base-uri($f) - where contains($path, '.xml') - order by string-length($path) - return $path - - return replace(xstring:substring-before-last($paths[1], '/'), '//', '/') -; - -(:~ - : get the base URI either from the data of the last call or from the configuration - :) -declare variable $wdb:edocBaseURL := - if ($wdb:configFile//config:server) - then normalize-space($wdb:configFile//config:server) - else - let $dir := try { xstring:substring-before-last(request:get-uri(), '/') } catch * { "" } - let $db := substring-after($wdb:edocBaseDB, 'db/') - let $local := xstring:substring-after($dir, $db) - let $path := if (string-length($local) > 0) - then xstring:substring-before($dir, $local) (: there is a local part, e.g. 'admin' :) - else $dir (: no local part, e.g. for view.html in app root :) - - return wdb:getServerApp() || replace($path, '//', '/') -; - -(: ~ - : get the base URL for REST calls - :) -declare variable $wdb:restURL := - if ($wdb:configFile//config:rest) - then normalize-space($wdb:configFile//config:rest) - else if ($wdb:edocBaseURL = "") - then rest:base-uri() || "/edoc" - else substring-before($wdb:edocBaseURL, substring-after($wdb:edocBaseDB, '/db/')) || "restxq/edoc/"; - - -(:~ - : the server role - :) -declare variable $wdb:role := - ($wdb:configFile//main:role/main:type, "standalone")[1] -; -(:~ - : the peer in a sandbox/publication configuration - :) -declare variable $wdb:peer := - if ($wdb:role != "standalone") - then $wdb:configFile//main:role/main:peer - else "" -; -(: END ALL-PURPOSE VARIABLES :) +declare namespace main = "https://github.com/dariok/wdbplus"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace rest = "http://exquery.org/ns/restxq"; +declare namespace tei = "http://www.tei-c.org/ns/1.0"; (: FUNCTIONS TO GET SERVER INFO :) (:~ @@ -105,9 +28,9 @@ declare variable $wdb:peer := : : @return (node()) HTML div :) -declare function wdb:test($node as node(), $model as map(*)) as node() { +declare function wdb:test( $node as node(), $model as map(*) ) as node() {
-

APP CONTEXT test on {$wdb:configFile//config:name}

+

APP CONTEXT test on {$config:configFile//config:name}

global variables (function.xqm)

@@ -128,13 +51,13 @@ declare function wdb:test($node as node(), $model as map(*)) as node() {
-

populateModel (app.xqm)

+

populateModel (model.xqm)

{ if (exists($model?id)) - then - let $computedModel := wdb:populateModel($model?id, "", map {}) - return wdbErr:get($computedModel, "") + then "currently, no model view is available" + (: let $computedModel := wdb:populateModel($model?id, "", map {}) + return wdbErr:get($computedModel, "") :) else "Keine ID zur Auswertung vorhanden" }
@@ -157,292 +80,9 @@ declare function wdb:test($node as node(), $model as map(*)) as node() {
}; - -(: ~ - : get the name of the server, possibly including the port - : If resolution fails, set the value in config.xml instead - : This cannot be used for RESTXQ - :) -declare function wdb:getServerApp() as xs:string { - (: config:server contains the full base URL :) - let $config := - let $scheme := substring-before($wdb:configFile//config:server, '//') - let $server := substring-before(substring-after($wdb:configFile//config:server, '//'), '/') - return if ($scheme != "") then $scheme || '//' || $server else () - - let $origin := try { request:get-header("Origin") } catch * { () } - let $request := try { - let $scheme := if (request:get-header-names() = 'X-Forwarded-Proto') - then normalize-space(request:get-header('X-Forwarded-Proto')) - else normalize-space(request:get-scheme()) - - return if (request:get-server-port() != 80) - then $scheme || '://' || request:get-server-name() || ':' || request:get-server-port() - else $scheme || '://' || request:get-server-name() - } catch * { () } - let $ref := try { - let $r := request:get-header('referer') - let $scheme := substring-before($r, '://') - let $server := substring-before(substring-after($r, '://'), '/') - return $scheme || '://' || $server - } catch * { () } - - let $server := ($config, $request, $ref, $origin) - return if (count($server) > 0) - then $server[1] - else "" -}; (: END FUNCTIONS TO GET SERVER INFO :) (: FUNCTIONS USED BY THE TEMPLATING SYSTEM :) -(:~ - : Templating function; called from layout.html. Entry point for content pages - :) -declare - %templates:default("view", "") - %templates:default("p", "") -function wdb:getEE($node as node(), $model as map(*), $id as xs:string, $view as xs:string, $p as xs:string) as item()* { - try { - let $newModel := wdb:populateModel($id, $view, $model, $p) - - return if ( contains($newModel?fileLoc, 'http') ) then - $newModel - else - let $last-modified := - wdbFiles:getModificationDate($newModel?filePathInfo?collectionPath, $newModel?filePathInfo?fileName) - => wdbFiles:ietfDate() - - let $requestedModified := ( - request:get-attribute("if-modified"), - request:get-header("If-Modified-Since") - )[1] - let $isModified := if ( $requestedModified != '' ) - then wdbFiles:evaluateIfModifiedSince($id, $requestedModified) - else 200 - - (: TODO: use a function to get the actual content language :) - return if ( count($newModel) = 1 and $isModified = 200 ) - then ( - response:set-header("Last-Modified", $last-modified), - - { - for $h in $node/* return - if ( $h/*[@data-template] ) then - for $c in $h/* return try { - templates:apply($c, $wdb:lookup, $newModel) - } catch * { - util:log("error", $err:description) - } - else - try { - templates:apply($h, $wdb:lookup, $newModel) - } catch * { - util:log("error", $err:description) - } - } - - ) - else if ( $isModified = 304 ) then - response:set-status-code(304) - else - - -
-

An unknown error has occurred

-
- - { util:log("error", $newModel) } - - } catch * { - util:log("error", $err:code || ': ' || $err:description), - wdbErr:error(map { - "code": $err:code, - "model": $model, - "err:value": $err:value, - "err:description": $err:description, - "err:additional": $err:additional, - "location": $err:module || '@' || $err:line-number || ':' || $err:column-number - }) - } -}; - -(:~ - : Populate the model with the most important global settings when displaying a file - : Moved to a separate function as this one may be called by other functions, too - : - : @param $id the id for the file to be displayed - : @param $view a string to be passed to the processing XSLT - : @param $p general parameter to be passed to the processing XSLT - : @return a map; in case of error, an HTML file - :) -declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $model as map(*) ) as item()* { - wdb:populateModel($id, $view, $model, "") -}; -declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $model as map(*), $p as xs:string ) as item()* { - let $filePathInfo := wdbFiles:getFullPath($id) - , $pathToFile := if ( map:keys($filePathInfo) = 'fileURL' ) - then - $filePathInfo?fileURL - else - $filePathInfo?collectionPath || '/' || $filePathInfo?fileName - , $pathToEd := $filePathInfo?projectPath - , $infoFileLoc := $filePathInfo?projectPath || '/wdbmeta.xml' - - let $ed := string(doc($infoFileLoc)/meta:projectMD/@xml:id) - - let $xsl := if ( $filePathInfo?fileName = "wdbmeta.xml" ) - then - (: TODO get path to XSL via function (use what’s in rest-files.xql) :) - xs:anyURI($wdb:data || '/resources/nav.xsl') - else wdb:getXslFromWdbMeta($infoFileLoc, $id, 'html') - - let $xslt := if (doc-available($xsl)) - then $xsl - else if (doc-available($pathToEd || '/' || $xsl)) - then $pathToEd || '/' || $xsl - else "" - - let $title := normalize-space((doc($pathToFile)//tei:title)[1]) - - let $proFile := wdb:findProjectXQM($pathToEd) - , $mainProject := substring-before($proFile, "project.xqm") - , $resource := $mainProject || "resources/" - - let $projectFunctions := for $function in doc($mainProject || "project-functions.xml")//function - return $function/@name || '#' || count($function/argument) - , $instanceFunctions := for $function in doc($wdb:data || "/instance-functions.xml")//function - return $function/@name || '#' || count($function/argument) - - let $header := if ( request:exists() ) - then map:merge( for $header in request:get-header-names() return map:entry($header, request:get-header($header)) ) - else () - , $requestUrl := if ( request:exists() ) - then request:get-url() - else () - - (: TODO read global parameters from config.xml and store as a map :) - let $map := map { - "ed": $ed, - "fileLoc": $pathToFile, - "filePathInfo": $filePathInfo, - "functions": map { "project": $projectFunctions, "instance": $instanceFunctions }, - "header": $header, - "id": $id, - "infoFileLoc": $infoFileLoc, - "mainEd": substring-after($mainProject, 'data/') => substring-before('/'), - "p": $p, - "pathToEd": $pathToEd, - "projectFile": $proFile, - "projectResources": $resource, - "requestUrl": $requestUrl, - "title": $title, - "view": $view, - "xslt": $xslt - } - - return $map -}; - -(: ~ - : Create the head for HTML files served via the templating system - : @created 2018-02-02 DK - :) -declare function wdb:getHead ( $node as node(), $model as map(*) ) as element(head) { - - - - - - - - { $model("title") } – { normalize-space($wdb:configFile//config:short) } - - { - if ( wdb:findProjectFunction($model, "wdbPF:overrideCssJs", 1) ) then - (wdb:getProjectFunction($model, "wdbPF:overrideCssJs", 1))($model) - else ( - , - if ( util:binary-doc-available($wdb:data || "/resources/wdb.css") ) - then - else (), - , - if ( util:binary-doc-available($wdb:data || "/resources/view.css") ) - then - else (), - wdb:getBlob($node, $model, 'jquery-ui-css'), - wdb:getProjectFiles($node, $model, 'css'), - wdb:getBlob($node, $model, 'jquery'), - wdb:getBlob($node, $model, 'jquery-ui-js'), - , - , - , - if ( util:binary-doc-available($wdb:data || "/resources/function.js") ) - then - else (), - wdb:getProjectFiles($node, $model, 'js') - ) - } - -}; - -(:~ - : return the header - if there is a project specific function, use it - : - : order of evaluation: - : 1. {$projectResources}/header.html – this must contain one html:header, the - : contents of which will be sent through the templating system - : 2. instance or project specific wdbPF:getHeader#1 - : 3. evaluation of all 4 constituents of the header in a row - : a) wdbPF:getHeaderLeft#1 or {$wdb:data}/resources/headerLeft.html or empty html:p - : b) wdbPF:getHeaderCentre#1 or {$wdb:data}/resources/headerCentre.html or html:h1 - : c) wdbPF:getHeaderMenu#1 or {$wdb:data}/resources/headerMenu.html or html:button - : d) wdbPF:getHeaderRight#1 or {$wdb:data}/resources/headerRight.html or empty html:p - :) -declare function wdb:getHeader ( $node as node(), $model as map(*) ) as element() { -
{ - if ( doc-available($model?projectResources || '/header.html') ) - then templates:apply(doc($model?projectResources || '/header.html')/header/*, $wdb:lookup, $model) - else if ( wdb:findProjectFunction($model, 'wdbPF:getHeader', 1) ) then - (wdb:getProjectFunction($model, "wdbPF:getHeader", 1))($model) - else ( - , -
{ - if ( wdb:findProjectFunction($model, 'wdbPF:getHeaderCentre', 1) ) then - (wdb:getProjectFunction($model, "wdbPF:getHeaderCentre", 1))($model) - else if ( doc-available($wdb:data || "/resources/headerCentre.html") ) then - templates:apply(doc($wdb:data || "/resources/headerCentre.html"), $wdb:lookup, $model)/* - else -

{$model("title")}

- }
, - , - - ) - }
-}; - -declare function wdb:pageTitle($node as node(), $model as map(*)) { - let $ti := $model("title") - return {normalize-space($wdb:configFile//main:short)} – {$ti} -}; - (:~ : generic function to wrap some info from the model in an HTML element via templating :) @@ -450,178 +90,12 @@ declare function wdb:wrapText ( $node as node(), $model as map(*), $key as xs:st element { node-name($node) } { $model($key) } }; -(:~ - : return the body - :) -declare function wdb:getContent($node as node(), $model as map(*)) { - let $file := $model("fileLoc") - - let $xslt := if (string-length($model?xslt) = 0) - then wdbErr:error(map {"code": "wdbErr:wdb0002", "model": $model}) - else $model("xslt") - - let $params := - - - - - - { - if ($model("view") != '') - then - else () - } - { - if ($model("p") != '') - then - else () - } - - - - (: do not stop transformation on ambiguous rule match and similar warnings :) - let $attr := - - (: TODO: use generic processXSL function (currently in restFiles.xql but to be moved) so there is only one way of doing things :) - (: TODO: consider removing this entirely and instead load content of main via AJAX :) - return - try { -
- { transform:transform(doc($file), doc($xslt), $params, $attr, "") } - { wdb:getLeftFooter($node, $model) } -
- } catch * { (util:log("error", - - {$file} - {$xslt} - {$params} - {$attr} - {$err:code || ': ' || $err:description} - {$err:module || '@' || $err:line-number ||':'||$err:column-number} - {$err:additional} - ), - wdbErr:error(map{"code": "wdbErr:wdb1001", "model": $model, "additional": $params, "error": map { - "code": $err:code, "desc": $err:description, "module": $err:module, "line": $err:line-number, - "col": $err:column-number, "add": $err:additional - }})) - } -}; - -(:~ - : return the global (i.e., full width) footer - : - : order of evaluation: - : 1. {$wdb:data}/resources/mainFooter.html - : 2. {$projectResources}/mainFooter.html - : 3. wdbPF:getMainFooter#1 - :) -declare function wdb:getGlobalFooter($node as node(), $model as map(*)) { - if ( doc-available($wdb:data || "/resources/mainFooter.html") ) - then templates:apply(doc($wdb:data || "/resources/mainFooter.html"), $wdb:lookup, $model) - else if ( doc-available($model?projectResources || '/mainFooter.html') ) - then templates:apply(doc($model?projectResources || '/mainFooter.html'), $wdb:lookup, $model) - else if ( wdb:findProjectFunction($model, "wdbPF:getMainFooter", 1) ) then - (wdb:getProjectFunction($model, "wdbPF:getMainFooter", 1))($model) - else () -}; - -declare function wdb:getLeftFooter($node as node(), $model as map(*)) as element()? { - if (doc-available($model?projectResources || "/footer.html")) then - templates:apply(doc($model?projectResources || "/footer.html"), $wdb:lookup, $model) - else if (wdb:findProjectFunction($model, "wdbPF:getProjectFooter", 1)) then - (wdb:getProjectFunction($model, "wdbPF:getProjectFooter", 1))($model) - else if (doc-available($wdb:edocBaseDB || "/resources/footer.html")) then - templates:apply(doc($wdb:edocBaseDB || "/resources/footer.html"), $wdb:lookup, $model) - else () -}; -declare function wdb:getRightFooter($node as node(), $model as map(*)) as element()? { - if (doc-available($model?projectResources || "/projectRightFooter.html")) then - templates:apply(doc($model?projectResources || "/projectRightFooter.html"), $wdb:lookup, $model) - else if (wdb:findProjectFunction($model, "wdbPF:getProjectRightFooter", 1)) then - (wdb:getProjectFunction($model, "wdbPF:getProjectRightFooter", 1))($model) - else if (doc-available($wdb:data || "/resources/rightFooter.html")) then - templates:apply(doc($wdb:data || "/resources/rightFooter.html"), $wdb:lookup, $model) - else () -}; - declare function wdb:getAnnotationDialogue ( $node as node(), $model as map(*) ) { () }; (: END FUNCTIONS USED BY THE TEMPLATING SYSTEM :) (: FUNCTIONS DEALING WITH PROJECTS AND RESOURCES :) -(:~ - : Return the full URI to the (edition) XML file with the given ID - : The scope is the whole data collection; documentation states in several places that file IDs need to be unique - : - : This function raises errors that are to be caught by the caller - : - : @param $id as xs:string: the file ID - : @return xs:string the full URI to the file within the database - : @throws wdbErr:wdb0000 - : @throws wdbErr:wdb0001 - :) -declare function wdb:getFilePath ( $id as xs:string ) as xs:string { - let $files := wdbFiles:getFilePaths($wdb:data, $id) - - (: do not just return a random URI but add some checks for better error messages: - : no files found or more than one TEI file found or only wdbmeta entry but no other info :) - let $pathToFile := if ( count($files) = 0 ) then - error( - QName('https://github.com/dariok/wdbErr', 'wdb0000'), - "no file with ID " || $id || " in " || $wdb:data, - map { "id": $id, "request": request:get-url() } - ) - else if ( count($files) > 1 ) then - error( - QName('https://github.com/dariok/wdbErr', 'wdb0001'), - "multiple files with ID " || $id || " in " || $wdb:data, - map { "id": $id, "request": request:get-url() } - ) - else if ( local-name($files[1]) = 'id' ) then - base-uri($files[1]) || '#' || $id - else - xstring:substring-before-last(base-uri($files[1]), '/') || '/' || $files[1] - - return if ( starts-with($files[1], '$') ) - then - let $peer := $files[1] => substring(2) => substring-before('/') - , $id := $files[1] => substring-after('/') - return $wdb:configFile/id($peer) || '/' || $id - else $pathToFile -}; - -(:~ - : Return the (relative or absolute) path to the project - : - : @param $id the ID of a resource within a project - : @param $absolute (optional) if true(), return an absolute URL - : - : @returns the path (relative) to the app root - :) -declare function wdb:getEdPath($id as xs:string, $absolute as xs:boolean) as xs:string { - let $file := collection($wdb:data)/id($id)[self::meta:file or self::meta:projectMD or self::meta:struct] - - let $edPath := if ( count($file) = 1 ) then - xstring:substring-before-last(base-uri($file), '/') - else if ( count($file) > 1 ) then - fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdb0001')) - else - fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdb0200')) - - return if ($absolute) then replace($edPath, '//', '/') else substring-after($edPath, $wdb:edocBaseDB) -}; - -(:~ - : Return the relative path to the project - : - : @param $id the ID of a resource within a project - : @return the path relative to the app root - :) -declare function wdb:getEdPath($id as xs:string) as xs:string { - wdb:getEdPath($id, false()) -}; - (:~ : Tries to return an absolute path for a path within a project : @@ -632,18 +106,7 @@ declare function wdb:getEdPath($id as xs:string) as xs:string { declare function wdb:getAbsolutePath ( $ed as xs:string, $path as xs:string ) { if ( starts-with($path, '/') ) then $path - else wdb:getEdPath($ed, true()) || "/" || $path -}; - -(:~ - : Return the ID of a project from a resource ID within the project - : - : @param $id the ID of a resource within a project - : @return the ID of the project - :) -declare function wdb:getEdFromFileId ($id as xs:string) as xs:string { - let $file := collection($wdb:data)/id($id)[self::meta:file] - return $file/ancestor::meta:projectMD/@xml:id + else (wdbFiles:getFullPath($ed))?projectPath || "/" || $path }; (: ~ @@ -655,10 +118,10 @@ declare function wdb:getEdFromFileId ($id as xs:string) as xs:string { : @return the path :) declare function wdb:getEdFromPath($path as xs:string, $absolute as xs:boolean) as xs:string { - let $tok := tokenize(xstring:substring-after($path, $wdb:edocBaseDB||'/'), '/') + let $tok := tokenize(xstring:substring-after($path, $config:edocBaseDB||'/'), '/') let $pa := for $i in 1 to count($tok) - let $t := $wdb:edocBaseDB || '.*' || string-join ($tok[position() < $i+1], '/') + let $t := $config:edocBaseDB || '.*' || string-join ($tok[position() < $i+1], '/') return xmldb:match-collection($t) let $path := if (count($pa) = 0) @@ -671,7 +134,7 @@ declare function wdb:getEdFromPath($path as xs:string, $absolute as xs:boolean) return if ( $absolute ) then $path[1] - else substring-after($path[1], $wdb:edocBaseDB||'/') + else substring-after($path[1], $config:edocBaseDB||'/') }; (:~ : Try ro load project specific XQuery to import CSS and JS @@ -681,8 +144,8 @@ declare function wdb:getProjectFiles ( $node as node(), $model as map(*), $type let $files := if ( wdb:findProjectFunction($model, 'wdbPF:getProjectFiles', 1) ) then (wdb:getProjectFunction($model, "wdbPF:getProjectFiles", 1))($model) else - let $css := wdb:findProjectFile($model?pathToEd, "/scripts/project.css") - , $js := wdb:findProjectFile($model?pathToEd, "/scripts/project.js") + let $css := wdb:findProjectFile($model?projectResources, "/css/project.css") + , $js := wdb:findProjectFile($model?projectResources, "/js/project.js") return ( if ( $css != "" ) @@ -729,22 +192,6 @@ declare function wdb:getProjectFunction ( $model as map(*), $name as xs:string, else () }; -(:~ - : Lookup a project's project.xqm: if present in $model("pathToEd"), use it; else, ascend and look for project.xqm - : there. Use if present. Ulitmately, if even $wdb:data/project.xqm does not exist, panic. - : - : @param $project a string representation of the path to the project - : @returns the path to a project.xqm if one was found; false() otherwise - :) -declare function wdb:findProjectXQM ( $project as xs:string ) { - if ( util:binary-doc-available($project || "/project.xqm") ) then - $project || "/project.xqm" - else if (substring-after($project, $wdb:data) = '') then - $wdb:data || "/instance.xqm" - else - wdb:findProjectXQM(xstring:substring-before-last($project, '/')) -}; - (:~ : Generic finder for files in the project hierarchy (bottom up) : it is assumed that this is a binary file @@ -753,19 +200,19 @@ declare function wdb:findProjectXQM ( $project as xs:string ) { : @param $fileName name of the file to search : @returns the full path to the file in the lowest position; if the file cannot be found, an empty URI is returned :) -declare function wdb:findProjectFile ( $pathToEd as xs:string, $fileName as xs:string ) as xs:anyURI { - if ( util:binary-doc-available($pathToEd || "/" || $fileName) ) then - xs:anyURI($pathToEd || "/" || $fileName) - else if ( substring-after($pathToEd, $wdb:data) = '' ) then +declare function wdb:findProjectFile ( $path as xs:string, $fileName as xs:string ) as xs:anyURI { + if ( util:binary-doc-available($path || "/" || $fileName) ) then + xs:anyURI($path || "/" || $fileName) + else if ( substring-after($path, $config:data) = '' ) then xs:anyURI("") else - wdb:findProjectFile(xstring:substring-before-last($pathToEd, '/'), $fileName) + wdb:findProjectFile(xstring:substring-before-last($path, '/'), $fileName) }; (: END FUNCTIONS DEALING WITH PROJECTS AND RESOURCES :) (: GENERAL HELPER FUNCTIONS :) declare function wdb:getUrl ( $path as xs:string ) as xs:string { - $wdb:edocBaseURL || substring-after($path, $wdb:edocBaseDB) + $config:edocBaseURL || substring-after($path, $config:edocBaseDB) }; (:~ @@ -782,117 +229,122 @@ declare function wdb:eval($function as xs:string) { declare function wdb:eval($function as xs:string, $cache-flag as xs:boolean, $external-variable as item()*) { util:eval($function, $cache-flag, $external-variable) }; - -(:~ - : Return the full path to the project collection by trying to find the meta file by the project ID - : - : @param $ed The ID of a project, to be found in meta:projectMD/@xml:id - : @return The path to the project - :) -declare function wdb:getProjectPathFromId ( $ed as xs:string ) as xs:string { - let $md := collection($wdb:data)/id($ed)[self::meta:projectMD] - - return xstring:substring-before-last(base-uri(($md)[1]), '/') -}; - -(:~ - : Get the meta data file from the ed path - :) -declare function wdb:getMetaFile($pathToEd) { - if ( doc-available($pathToEd||'/wdbmeta.xml') ) - then $pathToEd || '/wdbmeta.xml' - else fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdbErr:wdb0003')) -}; - -(:~ - : Get the meta data file by project ID - : - : @param $ed The project ID to be evaluated - :) -declare function wdb:getMetaElementFromEd ( $ed as xs:string ) as element() { - collection($wdb:data)/id($ed)[self::meta:projectMD] -}; (: END GENERAL HELPER FUNCTIONS :) (: LOCAL HELPER FUNCTIONS :) (:~ : Evaluate wdbmeta.xml to get the process used for transformation : - : @param $ed The (relative) path to the project : @param $id The ID of the file to be processed : @param $target The processing target to be used + : @param $infoFileLoc The location of the wdbmeta.xml file + : @param $view (optional) a view parameter for selecting the right process : : @returns The path to the XSLT :) -declare function wdb:getXslFromWdbMeta ( $infoFileLoc as xs:string, $id as xs:string, $target as xs:string ) as xs:string { - let $metaFile := doc($infoFileLoc), - $process := ( - $metaFile//meta:process[@target = $target], - $metaFile//meta:process[1] - )[1] +declare function wdb:getXslFromWdbMeta ( $infoFileLoc as xs:string, $id as xs:string, $target as xs:string ) as element(process)? { + wdb:getXslFromWdbMeta($infoFileLoc, $id, $target, "") +}; +declare function wdb:getXslFromWdbMeta ( $infoFileLoc as xs:string, $id as xs:string, $target as xs:string, $view as xs:string? ) as element(process)? { + let $metaFile := doc($infoFileLoc) + , $process := if ( $view != '' ) + then $metaFile//meta:process[@target = $target and @view = $view] + else $metaFile//meta:process[@target = $target and not(@view)] + , $base := if ( count($process) = 1 ) + then substring-before(base-uri($metaFile), 'wdbmeta.xml') + else if ( count($process) = 0 ) + then error( + QName('wdbRErr', 'wdb0002'), + "no process found for id " || $id || ", target '" || $target || "' and view '" || $view || "' in " || $infoFileLoc + ) + else error( + QName('wdbRErr', 'wdb0012'), + "multiple processes found for id " || $id || ", target '" || $target || "' and view '" || $view || "' in " || $infoFileLoc + ) - let $sel := for $c in $process/meta:command - return if ( $c/@refs ) then - (: if a list of IDREFS is given, this command matches if $id is part of that list :) - let $map := tokenize($c/@refs, ' ') - return if ( $map = $id ) then $c else () - else if ( $c/@regex and matches($id, $c/@regex) ) - (: if a regex is given and $id matches that regex, the command matches :) - then $c - else if ( $c/@group and $metaFile/id($id)/parent::meta:filegroup/@xml:id = $c/@group ) - then $c - else if ( not($c/@refs or $c/@regex or $c/@group) ) - (: if no selection method is given, the command is considered the default :) - then $c - else () (: neither refs nor regex match and no default given :) + let $sel := if ( $process/meta:command ) + then + for $c in $process/meta:command + return if ( $c/@refs ) then + (: if a list of IDREFS is given, this command matches if $id is part of that list :) + let $map := tokenize($c/@refs, ' ') + return if ( $map = $id ) then $base || $c else () + else if ( $c/@regex and matches($id, $c/@regex) ) + (: if a regex is given and $id matches that regex, the command matches :) + then $base || $c + else if ( $c/@group and $metaFile/id($id)/parent::meta:filegroup/@xml:id = $c/@group ) + then $base || $c + else if ( not($c/@refs or $c/@regex or $c/@group) ) + (: if no selection method is given, the command is considered the default :) + then $base || $c + else () (: neither refs nor regex match and no default given :) + (: if no command is defined, traverse up the project ancestors :) + else if ( $metaFile/meta:projectMD/meta:struct/*[1][self::meta:import] ) then + let $path := xstring:substring-before-last($infoFileLoc, '/') + , $parent := $metaFile/meta:projectMD/meta:struct/meta:import + return + wdb:getXslFromWdbMeta ($path || '/' || $parent/@path, $id, $target, $view) + else () (: As we check from most specific to default, the first command in the sequence is the right one :) - return ($sel)[1]/text() + return if ( $sel[1] instance of element(meta:process) ) + then $sel[1] + else if ( $sel[1] instance of xs:string ) + then + {$sel[1]} + + else + error( + QName('wdbRErr', 'wdb0002'), + "no process found for id " || $id || ", target '" || $target || "' and view '" || $view || "' in " || $infoFileLoc + ) }; -(: we need a lookup function for the templating system to work :) -declare variable $wdb:lookup := function($functionName as xs:string, $arity as xs:int) { - try { - function-lookup(xs:QName($functionName), $arity) - } catch * { - () - } +(:~ + : Apply a project specific XSLT to some XML + : + : @param $xml The XML to be transformed + : @param $edPath The path to the project + : @param $name The name of the XSLT file to be applied + : + : @returns The transformed XML + : + : The lookup order is: + : 1) project resources + : 2) instance resources + : 3) global resources + :) +declare function wdb:applySpecificXsl ( $xml as node(), $edPath as xs:string, $name as xs:string ) as node() { + wdb:applySpecificXsl($xml, $edPath, $name, ()) }; -(: END LOCAL HELPER FUNCTIONS :) - -(: HELPERS FOR REST AND HTTP REQUESTS :) -declare function wdb:parseMultipart ( $data, $header ) { - let $boundary := $header => substring-after('boundary=') => translate('"', '') - return map:merge( - for $m in tokenize($data, "--" || $boundary) return - if (string-length($m) lt 6) - then () +(:~ + : Apply a project specific XSLT to some XML + : + : @param $xml The XML to be transformed + : @param $edPath The path to the project + : @param $name The name of the XSLT file to be applied + : @param $parameters (optional) parameters to be passed to the XSLT + : + : @returns The transformed XML + : + : The lookup order is: + : 1) project resources + : 2) instance resources + : 3) global resources + :) +declare function wdb:applySpecificXsl ( $xml as node(), $edPath as xs:string, $name as xs:string, $parameters as element(parameters)? ) as node() { + let $xsl := if ( doc-available($edPath || "/resources/xsl/" || $name) ) then + doc($edPath || "/resources/xsl/" || $name) + else if ( doc-available("/db/apps/edoc/data/resources/xsl/" || $name) ) then + doc("/db/apps/edoc/data/resources/xsl/" || $name) else - let $parts := (tokenize($m, "(^\s*$){2}", "m"))[normalize-space() != ""] - let $header := map:merge( - for $line in tokenize($parts[1], "\n") return - if (normalize-space($line) eq "") - then () - else - let $val := $line => substring-after(': ') => normalize-space() - let $value := if (contains($val, '; ')) - then map:merge( - for $entry in tokenize($val, '; ') return - if (contains($entry, '=')) - then map:entry ( substring-before($entry, '='), translate(substring-after($entry, '='), '"', '') ) - else map:entry ( "text", $entry ) - ) - else $val - return map:entry(substring-before($line, ': '), $value) - ) - - (: empty lines in the body will also cause splitting; hence, recombine everything except the header :) - return map:entry(($header?Content-Disposition?name, 'name')[1], - map { "header" : $header, "body" : string-join($parts[position() > 1], '\n') } - ) - ) + doc("/db/apps/edoc/resources/xsl/" || $name) + + return transform:transform($xml, $xsl, $parameters) }; +(: END LOCAL HELPER FUNCTIONS :) +(: HELPERS FOR REST AND HTTP REQUESTS :) (:~ : Get a MIME type from an extension and an optional XML namespace : @@ -903,46 +355,34 @@ declare function wdb:parseMultipart ( $data, $header ) { declare function wdb:getContentTypeFromExt ( $extension as xs:string, $namespace as xs:anyURI? ) as xs:string { switch ( $extension ) case 'css' - return - 'text/css' + return 'text/css' case 'js' - return - 'application/javascript' + return 'application/javascript' case 'xql' case 'xqm' - return - 'application/xquery' + return 'application/xquery' case 'html' - return - 'text/html' + return 'text/html' case 'gif' - return - 'image/gif' + return 'image/gif' case 'png' - return - 'image/png' + return 'image/png' case 'json' - return - 'application/json' + return 'application/json' case 'zip' - return - 'application/zip' + return 'application/zip' case 'xml' - return - if ( $namespace = 'http://www.tei-c.org/ns/1.0' ) then - 'application/tei+xml' - else - 'application/xml' + return if ( $namespace = 'http://www.tei-c.org/ns/1.0' ) + then 'application/tei+xml' + else 'application/xml' case 'xsl' - return - 'application/xslt+xml' + return 'application/xslt+xml' default - return - 'application/octet-stream' + return 'application/octet-stream' }; declare function wdb:getBlob ( $node as node(), $model as map(*), $name as xs:string ) { - let $path := $wdb:configFile//config:source[@name = $name]/@path + let $path := $config:configFile//config:source[@name = $name]/@path return if ( ends-with($path, 'js') ) then diff --git a/edoc/modules/config.xqm b/edoc/modules/config.xqm deleted file mode 100644 index 8cd484d1..00000000 --- a/edoc/modules/config.xqm +++ /dev/null @@ -1,105 +0,0 @@ -xquery version "3.0"; - -(:~ - : A set of helper functions to access the application context from - : within a module. - :) -module namespace config = "http://exist-db.org/xquery/apps/config"; - -import module namespace templates = "http://exist-db.org/xquery/html-templating"; - -declare namespace repo = "http://exist-db.org/xquery/repo"; -declare namespace expath = "http://expath.org/ns/pkg"; - -(: - Determine the application root collection from the current module load path. -:) -declare variable $config:app-root := - let $rawPath := system:get-module-load-path() - let $modulePath := - (: strip the xmldb: part :) - if (starts-with($rawPath, "xmldb:exist://")) then - if (starts-with($rawPath, "xmldb:exist://embedded-eXist-server")) then - substring($rawPath, 36) - else - substring($rawPath, 15) - else - $rawPath - - return - substring-before($modulePath, "/modules") -; - -declare variable $config:data-root := $config:app-root || "/data"; - -declare variable $config:repo-descriptor := doc(concat($config:app-root, "/repo.xml"))/repo:meta; - -declare variable $config:expath-descriptor := doc(concat($config:app-root, "/expath-pkg.xml"))/expath:package; - -(:~ - : Resolve the given path using the current application context. - : If the app resides in the file system, - :) -declare function config:resolve($relPath as xs:string) { - (: es können auch absolute Pfade vorkommen; diese sollten nicht ersetzt werden :) - if (starts-with($relPath, '/db')) then - doc($relPath) - else if (starts-with($config:app-root, "/db")) then - doc(concat($config:app-root, "/", $relPath)) - else - doc(concat("file://", $config:app-root, "/", $relPath)) -}; - -(:~ - : Returns the repo.xml descriptor for the current application. - :) -declare function config:repo-descriptor() as element(repo:meta) { - $config:repo-descriptor -}; - -(:~ - : Returns the expath-pkg.xml descriptor for the current application. - :) -declare function config:expath-descriptor() as element(expath:package) { - $config:expath-descriptor -}; - -declare %templates:wrap function config:app-title($node as node(), $model as map(*)){ (:as text() {:) - (:$config:expath-descriptor/expath:title/text():) - '??' -}; - -declare function config:app-meta($node as node(), $model as map(*)) as element()* { - , - for $author in $config:repo-descriptor/repo:author - return - -}; - -(:~ - : For debugging: generates a table showing all properties defined - : in the application descriptors. - :) -declare function config:app-info($node as node(), $model as map(*)) { - let $expath := config:expath-descriptor() - let $repo := config:repo-descriptor() - return - - - - - - { - for $attr in ($expath/@*, $expath/*, $repo/*) - return - - - - - } - - - - -
app collection:{$config:app-root}
{node-name($attr)}:{$attr/string()}
Controller:{ request:get-attribute("$exist:controller") }
-}; \ No newline at end of file diff --git a/edoc/modules/entity.xqm b/edoc/modules/entity.xqm index 301a2e07..e93cd09c 100644 --- a/edoc/modules/entity.xqm +++ b/edoc/modules/entity.xqm @@ -2,24 +2,40 @@ xquery version "3.1"; module namespace wdbe = "https://github.com/dariok/wdbplus/entity"; -import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm"; -import module namespace console = "http://exist-db.org/xquery/console"; +import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "wdb-files.xqm"; -declare namespace tei = "http://www.tei-c.org/ns/1.0"; +declare namespace tei = "http://www.tei-c.org/ns/1.0"; +declare namespace transform = "http://exist-db.org/xquery/transform"; +declare namespace wdbErr = "https://github.com/dariok/wdbplus/errors"; (: $ent ID-String of the entity to be displayed – must be globally unique $ed ID of the project from which specific information shall be drawn :) -declare function wdbe:getEntity ( $node as node(), $model as map(*), $ent as xs:string, $ed as xs:string ) as map(*) { - let $edPath := wdb:getEdPath($ed, true()) - , $entry := collection($edPath || "/index")/id($ent) - - return map { "entry": $entry, "ent": $ent, "ed": $ed, "pathToEd": $edPath } +declare function wdbe:getEntity ( $node as node(), $model as map(*), $ent as xs:string, $ed as xs:string, $q as xs:string ) as map(*) { + let $fullPath := wdbFiles:getFullPath($ed) + , $collection := collection($fullPath?mainProject) + + let $entryEd := switch ( $q ) + case "per" + return $collection/id($ent)[self::tei:person and ancestor::*:text] + case "org" + return $collection/id($ent)[self::tei:org and ancestor::*:text] + case "pla" + return $collection/id($ent)[self::tei:place and ancestor::*:text] + case "bib" + return $collection/id($ent)[self::tei:bibl and ancestor::*:text] + default + return error(xs:QName("wdbErr:wdb3010"), "unknown entity type", map { "type": $q }) + + (: TODO: this only uses a project specific list* file; we want ot use (or at least support) globals files :) + return map { "entry": $entryEd[1], "ed": $ed, "pathToEd": $fullPath?mainProject } }; declare function wdbe:getEntityBody( $node as node(), $model as map(*) ) as element() { - let $xsl := if ( doc-available($model?pathToEd || "/resources/tei-index.xsl") ) - then doc($model?pathToEd || "/resources/tei-index.xsl") - else doc("/db/apps/edoc/resources/tei-index.xsl") + let $xsl := if ( doc-available($model?pathToEd || "/resources/xsl/tei-index.xsl") ) + then doc($model?pathToEd || "/resources/xsl/tei-index.xsl") + else if ( doc-available("/db/apps/edoc/data/resources/xsl/tei-index.xsl") ) + then doc("/db/apps/edoc/data/resources/xsl/tei-index.xsl") + else doc("/db/apps/edoc/resources/xsl/tei-index.xsl") , $result := transform:transform($model?entry, $xsl, ()) return if ( count($result) = 1 ) diff --git a/edoc/modules/error.xqm b/edoc/modules/error.xqm index bfa56cfc..71d4728b 100644 --- a/edoc/modules/error.xqm +++ b/edoc/modules/error.xqm @@ -2,10 +2,11 @@ xquery version "3.1"; module namespace wdbErr = "https://github.com/dariok/wdbplus/errors"; -import module namespace response = "http://exist-db.org/xquery/response" at "java:org.exist.xquery.functions.response.ResponseModule"; -import module namespace map = "http://www.w3.org/2005/xpath-functions/map" at "java:org.exist.xquery.functions.map.MapModule"; -import module namespace functx = "http://www.functx.com" at "/db/system/repo/functx-1.0.1/functx/functx.xq"; +import module namespace config = "https://github.com/dariok/wdbplus/config" at "wdb-config.xqm"; +import module namespace functx = "http://www.functx.com"; +declare namespace response = "http://exist-db.org/xquery/response"; +declare namespace map = "http://www.w3.org/2005/xpath-functions/map"; declare function wdbErr:error ( $data as map (*) ) as item()+ { let $error := switch ( xs:string($data("code")) ) @@ -33,46 +34,53 @@ declare function wdbErr:error ( $data as map (*) ) as item()+ { case "wdbErr:wdb3001" return "Error creating model in function.xqm" default return "An unknown error has occurred: " || $data("code") - let $statusCode := if ( xs:string($data?code) = ("wdbErr:wdb0200", "wdbErr:wdb0000", "wdbErr:wdb0404") ) + let $statusCode := if ( xs:string($data?code) = ("wdbErr:wdb0200", "wdbErr:wdb0000", "wdb0000", "wdbErr:wdb0404") ) then 404 else 418 let $errorContent := if ( $statusCode = 404 ) - then -
-

Seite nicht gefunden

-

Leider konnten wir die angegebene Seite nicht finden

-
- else -
-

Something has gone wrong...

-

{$error}

- { wdbErr:get(map:merge(($data, map:entry("user", sm:id()))), '') } -
+ then ( +

Seite nicht gefunden

, +

Leider konnten wir die angegebene Seite nicht finden

+ ) + else ( +

Something has gone wrong...

, +

{$error}

, +
+ Logged error details: + { wdbErr:get(map:merge(($data, map:entry("user", sm:id()))), '') } +
+ ) return ( util:log("error", $error), util:log("info", $data), - response:set-status-code($statusCode), + if ( response:exists() ) then response:set-status-code($statusCode) else (), + (: TODO we need to check whether we already have a page at this point and only need to return a div or whether we + need a complete HTML file :) ERROR - + - , + , + , + if ( util:binary-doc-available($config:data || "/resources/js/function.js") ) + then + else (), + wdb:getProjectFiles($node, $model, 'js') + ) + } + +}; + +(:~ + : return the header - if there is a project specific function, use it + : + : order of evaluation: + : 1. {$projectResources}/html/header.html – this must contain one html:header, the + : contents of which will be sent through the templating system + : 2. instance or project specific wdbPF:getHeader#1 + : 3. evaluation of all 4 constituents of the header in a row + : a) wdbPF:getHeaderLeft#1 or {$config:data}/resources/html/headerLeft.html or empty html:p + : b) wdbPF:getHeaderCentre#1 or {$config:data}/resources/html/headerCentre.html or html:h1 + : c) wdbPF:getHeaderMenu#1 or {$config:data}/resources/html/headerMenu.html or html:button + : d) wdbPF:getHeaderRight#1 or {$config:data}/resources/html/headerRight.html or empty html:p + :) +declare function wdbv:getHeader ( $node as node(), $model as map(*) ) as element() { +
{ + if ( doc-available($model?projectResources || '/html/header.html') ) + then templates:apply(doc($model?projectResources || '/html/header.html')/header/*, $wdbv:lookup, $model) + else if ( wdb:findProjectFunction($model, 'wdbPF:getHeader', 1) ) then + (wdb:getProjectFunction($model, "wdbPF:getHeader", 1))($model) + else ( + , +
{ + if ( wdb:findProjectFunction($model, 'wdbPF:getHeaderCentre', 1) ) then + (wdb:getProjectFunction($model, "wdbPF:getHeaderCentre", 1))($model) + else if ( doc-available($config:data || "/resources/html/headerCentre.html") ) then + templates:apply(doc($config:data || "/resources/html/headerCentre.html"), $wdbv:lookup, $model)/* + else +

{$model("title")}

+ }
, + , + + ) + }
+}; + +(:~ + : return the body + :) +declare function wdbv:getContent ( $node as node(), $model as map(*) ) { + (: TODO: consider removing this entirely and instead load content of main via AJAX :) + try { +
+ { (wdbProc:getContent($model?id, $model?xslt, $model?view, $model))?content } + { wdbv:getLeftFooter($node, $model) } +
+ } catch err:XPTY0004 { + wdbErr:error( + map { + "code": "wdbErr:wdb0002", + "model": $model, + "error": map { + "code": $err:code, + "desc": $err:description, + "module": $err:module, + "line": $err:line-number, + "col": $err:column-number, + "add": $err:additional + } + } + )//main + } catch * { + wdbErr:error( + map{ + "code": "wdbErr:wdb1001", + "model": $model, + "error": map { + "code": $err:code, + "desc": $err:description, + "module": $err:module, + "line": $err:line-number, + "col": $err:column-number, + "add": $err:additional + }}) + } +}; + +(: TODO: replace the repetitive if (doc-avilable(a) then a else if (doc-available(b) then b else c) with a function :) +(:~ + : return the global (i.e., full width) footer + : + : order of evaluation: + : 1. {$config:data}/resources/html/mainFooter.html + : 2. {$projectResources}/html/mainFooter.html + : 3. wdbPF:getMainFooter#1 + :) +declare function wdbv:getGlobalFooter ( $node as node(), $model as map(*) ) as element(footer)? { + if ( doc-available($config:data || "/resources/html/mainFooter.html") ) + then templates:apply(doc($config:data || "/resources/html/mainFooter.html"), $wdbv:lookup, $model) + else if ( doc-available($model?projectResources || '/html/mainFooter.html') ) + then templates:apply(doc($model?projectResources || '/html/mainFooter.html'), $wdbv:lookup, $model) + else if ( wdb:findProjectFunction($model, "wdbPF:getMainFooter", 1) ) then + (wdb:getProjectFunction($model, "wdbPF:getMainFooter", 1))($model) + else () +}; +declare function wdbv:getLeftFooter ( $node as node(), $model as map(*) ) as element(footer)? { + if (doc-available($model?projectResources || "/html/footer.html")) then + templates:apply(doc($model?projectResources || "/html/footer.html"), $wdbv:lookup, $model) + else if (wdb:findProjectFunction($model, "wdbPF:getProjectFooter", 1)) then + (wdb:getProjectFunction($model, "wdbPF:getProjectFooter", 1))($model) + else if (doc-available($config:edocBaseDB || "/resources/html/footer.html")) then + templates:apply(doc($config:edocBaseDB || "/resources/html/footer.html"), $wdbv:lookup, $model) + else () +}; +declare function wdbv:getRightFooter ( $node as node(), $model as map(*) ) as element(footer)? { + if (doc-available($model?projectResources || "/html/projectRightFooter.html")) then + templates:apply(doc($model?projectResources || "/html/projectRightFooter.html"), $wdbv:lookup, $model) + else if (wdb:findProjectFunction($model, "wdbPF:getProjectRightFooter", 1)) then + (wdb:getProjectFunction($model, "wdbPF:getProjectRightFooter", 1))($model) + else if (doc-available($config:data || "/resourceshtml//rightFooter.html")) then + templates:apply(doc($config:data || "/resources/html/rightFooter.html"), $wdbv:lookup, $model) + else () +}; diff --git a/edoc/modules/wdb-config.xqm b/edoc/modules/wdb-config.xqm new file mode 100644 index 00000000..c27942ff --- /dev/null +++ b/edoc/modules/wdb-config.xqm @@ -0,0 +1,47 @@ +xquery version "3.1"; + +module namespace config = "https://github.com/dariok/wdbplus/config"; + +(: global variables are defined here. These used to be in app.xqm but have been moved here to avoid circular + : dependencies when importing app.xqm :) + +(:~ + : load the config file + : See https://github.com/dariok/wdbplus/wiki/Global-Configuration + :) +declare variable $config:configFile := doc('../config.xml'); + +(:~ + : the base of this instance within the db + :) +declare variable $config:edocBaseDB := $config:configFile => base-uri() => substring-before('/config.xml'); + +(:~ + : Get the data collection. Since v4.0, we only support setting this in the config file – for standard installations, + the default will do just fine. + :) +declare variable $config:data := $config:configFile//config:data; + +(:~ + : get the base URI from the configuration + :) +declare variable $config:edocBaseURL := $config:configFile//config:server; + +(: ~ + : get the base URL for REST calls + :) +declare variable $config:restURL := $config:configFile//config:rest[1]; + +(:~ + : the server role + :) +declare variable $config:role := $config:configFile//config:role/config:type; + +(:~ + : the peer in a sandbox/publication configuration + :) +declare variable $config:peer := + if ( $config:role != "standalone" ) + then $config:configFile//config:role/config:peer + else "" +; diff --git a/edoc/modules/wdb-files.xqm b/edoc/modules/wdb-files.xqm index 8579ea14..16de7804 100644 --- a/edoc/modules/wdb-files.xqm +++ b/edoc/modules/wdb-files.xqm @@ -14,8 +14,10 @@ module namespace wdbFiles = "https://github.com/dariok/wdbplus/files"; import module namespace functx = "http://www.functx.com" at "/db/system/repo/functx-1.0.1/functx/functx.xq"; -declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; -declare namespace wdbErr = "https://github.com/dariok/wdbplus/errors"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace request = "http://exist-db.org/xquery/request"; +declare namespace util = "http://exist-db.org/xquery/util"; +declare namespace wdbErr = "https://github.com/dariok/wdbplus/errors"; (:~ : Return the path to all Resources with a given ID @@ -57,51 +59,98 @@ declare function wdbFiles:getAbsolutePath ( $path as attribute() ) as xs:anyURI : project collection) and its file name : : @param $id as xs:string: the ID of the file (which should be unique) - : @return map(string, string) with keys "collectionPath", "fileName", "projectPath" + : @return map(string, string) with keys including "kind", "projectPath", "collectionPath", and "fileName" : @throws wdbErr:wdb0000 : @throws wdbErr:wdb0001 :) -declare function wdbFiles:getFullPath ( $id as xs:string ) as map( xs:string, xs:string, xs:string? )? { - let $file := collection("/db")/id($id)[self::meta:file] +declare function wdbFiles:getFullPath ( $id as xs:string ) as map( xs:string, xs:string )? { + let $file-hint := doc("/db/apps/edoc/index/file-index.xml")/id($id) + , $project-hint := doc("/db/apps/edoc/index/project-index.xml")/id($id) + , $file := ( doc($file-hint[1]/@project)/id($id), doc($project-hint[1]/@path || "/wdbmeta.xml")/id($id) ) + , $request := if ( request:exists() ) then request:get-url() else 'no request context' return if ( count($file) = 0 ) then error( QName('https://github.com/dariok/wdbErr', 'wdb0000'), "no file with ID " || $id, - map { "id": $id, "request": request:get-url() } + map { "id": $id, "request": $request } ) - else if ( count($file) > 1 ) then + else if ( count($file-hint) gt 1 ) then error( QName('https://github.com/dariok/wdbErr', 'wdb0001'), "multiple files with ID " || $id, - map { "id": $id, "request": request:get-url() } + map { "id": $id, "request": $request } ) - else if ( $file[self::meta:projectMD] ) then - let $projectPath := base-uri($file) => substring-before("wdbmeta.xml") + else if ( count($project-hint) gt 1 ) then + error( + QName('https://github.com/dariok/wdbErr', 'wdb1001'), + "multiple projects with ID " || $id, + map { "id": $id, "request": $request } + ) + else if ( $file[self::meta:projectMD or self::meta:struct] ) then + let $projectPath := base-uri($file[self::meta:projectMD or self::meta:struct]) => substring-before("wdbmeta.xml") return map { + "kind": "project", "projectPath": $projectPath, "collectionPath": $projectPath, - "fileName": "wdbmeta.xml" + "fileName": "wdbmeta.xml", + "mainProject": wdbFiles:findMainProject($projectPath), + "parentProject": wdbFiles:findParentProject($projectPath, $id) } else if ( starts-with($file/@path, '$') ) then let $projectPath := base-uri($file) => substring-before("wdbmeta.xml") , $peer := $file => substring(2) => substring-before('/') , $id := $file => substring-after('/') return map { + "kind": "peer", "projectPath": $projectPath, "fileURL": doc("../config.xml")/id($peer) || '/' || $id } else - let $projectPath := base-uri($file) => substring-before("wdbmeta.xml") - , $path := $projectPath || $file/@path + let $projectPath := base-uri($file[self::meta:file]) => substring-before("wdbmeta.xml") + , $path := $projectPath || $file[self::meta:file]/@path - return map{ + return map { + "kind": "file", "projectPath": $projectPath, "collectionPath": functx:substring-before-last($path, '/') , - "fileName": functx:substring-after-last($path, '/') + "fileName": functx:substring-after-last($path, '/'), + "mainProject": wdbFiles:findMainProject($projectPath) } }; +(:~ + : Find the parent project: if a wdbmeta.xml imports the current project, use it; else, ascend and look for an import + : there. Use if present. Ulitmately, if even $wdb:data/wdbmeta.xml does not exist, panic. + : + : @param $projectPath a string representation of the path to the project + : @returns the path to the main project + :) +declare function wdbFiles:findParentProject ( $projectPath as xs:string, $id as xs:string ) as xs:string { + if ( doc-available($projectPath || "/wdbmeta.xml") and doc($projectPath || "/wdbmeta.xml")//meta:ptr[@xml:id = $id] ) then + $projectPath + else if ( substring-after($projectPath, "/db/apps/edoc/data") = '' ) then + "/db/apps/edoc/data/" + else + wdbFiles:findParentProject(functx:substring-before-last($projectPath, '/'), $id) +}; + +(:~ + : Find the main project: if a project.xqm is present in $projectPath, use it; else, ascend and look for project.xqm + : there. Use if present. Ulitmately, if even $wdb:data/project.xqm does not exist, panic. + : + : @param $projectPath a string representation of the path to the project + : @returns the path to the main project + :) +declare function wdbFiles:findMainProject ( $projectPath as xs:string ) as xs:string { + if ( util:binary-doc-available($projectPath || "/project.xqm") ) then + $projectPath + else if ( substring-after($projectPath, "/db/apps/edoc/data") = '' ) then + "/db/apps/edoc/data/" + else + wdbFiles:findMainProject(functx:substring-before-last($projectPath, '/')) +}; + (:~ : Check whether the current user has the right to access the file with the given mode : @@ -160,7 +209,10 @@ declare function wdbFiles:evaluateIfModifiedSince ( $id as xs:string, $requested :) declare function wdbFiles:evaluateIfModifiedSince ( $collectionPath as xs:string, $fileName as xs:string, $requestedModified as xs:string+ ) as xs:double { let $modifiedWithoutMillisecs := wdbFiles:getModificationDate($collectionPath, $fileName) - , $requestedModifiedParsed := parse-ietf-date(string-join($requestedModified)) + , $requestedModifiedParsed := + if ( $requestedModified castable as xs:dateTime ) + then $requestedModified + else parse-ietf-date(string-join($requestedModified)) return if ( $requestedModifiedParsed lt $modifiedWithoutMillisecs ) then 200 @@ -168,9 +220,9 @@ declare function wdbFiles:evaluateIfModifiedSince ( $collectionPath as xs:string }; (:~ - : format da given datetime as IETF date + : format a given datetime as IETF date : - : @param gmtDateTime an xs:dataTime adjust to GMT + : @param gmtDateTime an xs:dataTime adjusted to GMT : @returns xs:string formated as an IETF date :) declare function wdbFiles:ietfDate ( $gmtDateTime as xs:dateTime ) as xs:string { diff --git a/edoc/modules/wdb-process.xqm b/edoc/modules/wdb-process.xqm new file mode 100644 index 00000000..008aa57f --- /dev/null +++ b/edoc/modules/wdb-process.xqm @@ -0,0 +1,98 @@ +xquery version "3.1"; + +module namespace wdbProc = "https://github.com/dariok/wdbplus/Process"; + +import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm"; + +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; + +declare function wdbProc:getContent ( $id as xs:string, $process as element(), $view as xs:string, $model as map(*) ) as map(*) { + let $effectiveModel := map:merge(( + map:remove($model, ("id", "process", "view", "xslt")), + map { + "id": ($model?id, $id)[1], + "process": ($model?process, $process)[1], + "view": ($model?view, $view)[1], + "xslt": ($model?xslt, $process)[1] + } + )) + + (: TODO if multiple commands are defined, check that one is actually applicable – #395 :) + (: TODO pass the position of this command on to the processing function or pass target and view on :) + (: TODO once dev on wdbmeta, -- steps -- is done, implement these here – #394:) + switch ( $process[1]/meta:command/@type ) + case "xsl" return + let $content := wdbProc:processXSL($effectiveModel) + return map { "status": $content?status, "content": $content?content } + case "xquery" return + let $content := wdbProc:processXQuery($effectiveModel) + return map { "status": $content?status, "content": $content?content } + default return + map { "status": 500, "content": "Invalid command type " || ($process[1]/meta:command/@type, '?')[1] } +}; + +(: TODO: use parameter list as defined in app.xqm :) +(: TODO: inject additional parameters? :) +declare function wdbProc:processXSL ( $model as map(*) ) as map(*) { + (: this is necessary to catch meta:struct with IDs (for a sub-corpus) :) + let $file := if ( ends-with($model?fileLoc, 'wdbmeta.xml') ) + then $model?fileLoc || '#' || $model?id + else $model?fileLoc + + (: do not stop transformation on ambiguous rule match and similar warnings :) + let $attr := + + + + , $params := + + + + + + { + if ( $model?view != '' ) + then + else () + } + { + if ($model?p != '') + then + else () + } + + + + + (: TODO: for multiple commands, we need recursion here :) + return if ( not(sm:has-access($file, 'r')) ) + then map { "status": 403, "content": "File " || $file || " is not readable" } + else map { + "status": 200, + "content": transform:transform( + doc($file), + doc(normalize-space(($model?xslt)/meta:command)), + $params, + $attr, + "" + ) + } +}; + +declare function wdbProc:processXQuery ( $model as map(*) ) as map(*) { + let $function := $model?process/meta:command/text() + + return if ( starts-with($function, 'http') or starts-with($function, '/') ) + then () (: TODO :) + else if ( wdb:findProjectFunction($model, $function, 2) ) then + try { + map { + "status": 200, + "content": wdb:eval($function || "($id, $process)", false(), (xs:QName("id"), $model?id, xs:QName("process"), $model?process)) + } + } catch * { + map { "status": 500, "content": $err:description } + } + else + map { "status": 500, "content": "function " || $function || " not found" } +}; diff --git a/edoc/modules/wdb-request.xqm b/edoc/modules/wdb-request.xqm new file mode 100644 index 00000000..ff45a35a --- /dev/null +++ b/edoc/modules/wdb-request.xqm @@ -0,0 +1,39 @@ +xquery version "3.1"; + +module namespace wdbRequest = "https://github.com/dariok/wdbplus/Request"; + +declare function wdbRequest:parseMultipart ( $data as xs:string, $header as xs:string ) as map(*) { + let $boundary := $header => substring-after('boundary=') => translate('"', '') + + return map:merge( + (: split multipart data at the boundary :) + for $m in tokenize($data, "--" || $boundary) + (: ignore the last part after the final boundary, which is just '--' :) + where string-length($m) gt 6 + + (: the header is separated by an empty line :) + let $parts := (tokenize($m, "(^\s*$){2}", "m"))[normalize-space() != ""] + + let $header := map:merge( + for $line in tokenize($parts[1], "\n") + where normalize-space($line) != "" + + let $val := $line => substring-after(': ') => normalize-space() + let $value := if ( contains($val, '; ') ) + (: combined header fields; e.g., Content-Disposition :) + then map:merge( + for $entry in tokenize($val, '; ') return + if ( contains($entry, '=') ) + then map:entry ( substring-before($entry, '='), translate(substring-after($entry, '='), '"', '') ) + else map:entry ( "text", $entry ) + ) + else $val + return map:entry(substring-before($line, ': '), $value) + ) + + (: empty lines in the body will also cause splitting; hence, recombine everything except the header :) + return map:entry(($header?Content-Disposition?name, 'name')[1], + map { "header" : $header, "body" : string-join($parts[position() > 1], '\n') } + ) + ) +}; diff --git a/edoc/post-install.xql b/edoc/post-install.xql index 8153df4d..7bbb7668 100644 --- a/edoc/post-install.xql +++ b/edoc/post-install.xql @@ -12,14 +12,16 @@ let $indexConfig := ( xmldb:create-collection("/db/system/config/db/apps/edoc", "annotations"), xmldb:create-collection("/db/system/config/db/apps/edoc", "data"), xmldb:create-collection("/db/system/config/db/apps/edoc", "rest"), + xmldb:create-collection("/db/system/config/db/apps/edoc/data", "documentation"), xmldb:store("/db/system/config/db/apps/edoc/addins", "collection.xconf", doc($targetCollection || "/config/edoc/addins/collection.xconf")), xmldb:store("/db/system/config/db/apps/edoc/annotations", "collection.xconf", doc($targetCollection || "/config/edoc/annotations/collection.xconf")), xmldb:store("/db/system/config/db/apps/edoc/data", "collection.xconf", doc($targetCollection || "/config/edoc/data/collection.xconf")), - xmldb:store("/db/system/config/db/apps/edoc/rest", "collection.xconf", doc($targetCollection || "/config/edoc/rest/collection.xconf")) + xmldb:store("/db/system/config/db/apps/edoc/rest", "collection.xconf", doc($targetCollection || "/config/edoc/rest/collection.xconf")), + xmldb:store("/db/system/config/db/apps/edoc/data/documentation", "collection.xconf", doc($targetCollection || "/config/edoc/data/documentation/collection.xconf")) ) let $collsr := ( - "/modules", "/templates", "/resources/css", "/resources/scripts", "/resources/xsl" + "/modules", "/templates", "/resources/css", "/resources/js", "/resources/xsl" ) let $chmod := ( @@ -36,6 +38,8 @@ let $chmod := ( return sm:chmod(xs:anyURI($targetCollection || '/modules/' || $xql), 'r-xr-xr-x'), for $global in xmldb:get-child-resources($targetCollection || '/global') return sm:chmod(xs:anyURI($targetCollection || '/global/' || $global), 'rw-rw-r--'), + for $global in xmldb:get-child-resources($targetCollection || '/logs') + return sm:chmod(xs:anyURI($targetCollection || '/logs/' || $global), 'rw-rw-rw-'), sm:chmod(xs:anyURI($targetCollection || '/config.xml'), 'rw-rw-r--'), sm:chmod(xs:anyURI($targetCollection || '/controller.xql'), 'r-xr-xr-x'), sm:chmod(xs:anyURI($targetCollection || '/data/wdbmeta.xml'), 'rw-rw-r--'), @@ -51,8 +55,9 @@ let $chmod := ( let $reindex := ( xmldb:reindex($targetCollection || '/data'), xmldb:reindex($targetCollection || '/rest'), - xmldb:reindex($targetCollection || '/annotation'), - xmldb:reindex($targetCollection || '/addins') + xmldb:reindex($targetCollection || '/annotations'), + xmldb:reindex($targetCollection || '/addins'), + xmldb:reindex($targetCollection || '/admin') ) return ($reindex, $chmod) \ No newline at end of file diff --git a/edoc/resources/blobs/.gitkeep b/edoc/resources/blobs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/resources/css/jquery-ui.min.css b/edoc/resources/css/jquery-ui.min.css new file mode 100644 index 00000000..5dc9706e --- /dev/null +++ b/edoc/resources/css/jquery-ui.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.14.2 - 2026-01-29 +* https://jqueryui.com +* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit https://jqueryui.com/themeroller/?bgColorDefault=%23f6f6f6&borderColorDefault=%23c5c5c5&fcDefault=%23454545&bgColorHover=%23ededed&borderColorHover=%23cccccc&fcHover=%232b2b2b&bgColorActive=%23007fff&borderColorActive=%23003eff&fcActive=%23ffffff&bgColorHeader=%23e9e9e9&borderColorHeader=%23dddddd&fcHeader=%23333333&bgColorContent=%23ffffff&borderColorContent=%23dddddd&fcContent=%23333333&bgColorHighlight=%23fffa90&borderColorHighlight=%23dad55e&fcHighlight=%23777620&bgColorError=%23fddfdf&borderColorError=%23f1a899&fcError=%235f3f3f&bgColorOverlay=%23aaaaaa&opacityOverlay=.3&bgColorShadow=%23666666&opacityShadow=.3&offsetTopShadow=0px&offsetLeftShadow=0px&thicknessShadow=5px&cornerRadiusShadow=8px&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif&fwDefault=normal&cornerRadius=3px&bgTextureDefault=flat&bgTextureHover=flat&bgTextureActive=flat&bgTextureHeader=flat&bgTextureContent=flat&bgTextureHighlight=flat&bgTextureError=flat&bgTextureOverlay=flat&bgTextureShadow=flat&bgImgOpacityDefault=75&bgImgOpacityHover=75&bgImgOpacityActive=65&bgImgOpacityHeader=75&bgImgOpacityContent=75&bgImgOpacityHighlight=55&bgImgOpacityError=95&bgImgOpacityOverlay=0&bgImgOpacityShadow=0&iconColorActive=%23ffffff&iconColorContent=%23444444&iconColorDefault=%23777777&iconColorError=%23cc0000&iconColorHeader=%23444444&iconColorHighlight=%23777620&iconColorHover=%23555555&opacityOverlayPerc=30&opacityShadowPerc=30&bgImgUrlActive=&bgImgUrlContent=&bgImgUrlDefault=&bgImgUrlError=&bgImgUrlHeader=&bgImgUrlHighlight=&bgImgUrlHover=&bgImgUrlOverlay=&bgImgUrlShadow=&iconsActive=url(%22images%2Fui-icons_ffffff_256x240.png%22)&iconsContent=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsDefault=url(%22images%2Fui-icons_777777_256x240.png%22)&iconsError=url(%22images%2Fui-icons_cc0000_256x240.png%22)&iconsHeader=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsHighlight=url(%22images%2Fui-icons_777620_256x240.png%22)&iconsHover=url(%22images%2Fui-icons_555555_256x240.png%22)&bgDefaultRepeat=&bgHoverRepeat=&bgActiveRepeat=&bgHeaderRepeat=&bgContentRepeat=&bgHighlightRepeat=&bgErrorRepeat=&bgOverlayRepeat=&bgShadowRepeat=&bgDefaultYPos=&bgHoverYPos=&bgActiveYPos=&bgHeaderYPos=&bgContentYPos=&bgHighlightYPos=&bgErrorYPos=&bgOverlayYPos=&bgShadowYPos=&bgDefaultXPos=&bgHoverXPos=&bgActiveXPos=&bgHeaderXPos=&bgContentXPos=&bgHighlightXPos=&bgErrorXPos=&bgOverlayXPos=&bgShadowXPos= +* Copyright OpenJS Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;user-select:none}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:pointer;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;background-image:none}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank.ui-icon-blank.ui-icon-blank{background-image:none}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3}.ui-widget-shadow{box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/edoc/resources/css/swagger-ui.css b/edoc/resources/css/swagger-ui.css new file mode 100644 index 00000000..d2ea0226 --- /dev/null +++ b/edoc/resources/css/swagger-ui.css @@ -0,0 +1,3 @@ +.swagger-ui{color:#3b4151;font-family:sans-serif/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */}.swagger-ui html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.15}.swagger-ui body{margin:0}.swagger-ui article,.swagger-ui aside,.swagger-ui footer,.swagger-ui header,.swagger-ui nav,.swagger-ui section{display:block}.swagger-ui h1{font-size:2em;margin:.67em 0}.swagger-ui figcaption,.swagger-ui figure,.swagger-ui main{display:block}.swagger-ui figure{margin:1em 40px}.swagger-ui hr{box-sizing:content-box;height:0;overflow:visible}.swagger-ui pre{font-family:monospace,monospace;font-size:1em}.swagger-ui a{-webkit-text-decoration-skip:objects;background-color:transparent}.swagger-ui abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.swagger-ui b,.swagger-ui strong{font-weight:inherit;font-weight:bolder}.swagger-ui code,.swagger-ui kbd,.swagger-ui samp{font-family:monospace,monospace;font-size:1em}.swagger-ui dfn{font-style:italic}.swagger-ui mark{background-color:#ff0;color:#000}.swagger-ui small{font-size:80%}.swagger-ui sub,.swagger-ui sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.swagger-ui sub{bottom:-.25em}.swagger-ui sup{top:-.5em}.swagger-ui audio,.swagger-ui video{display:inline-block}.swagger-ui audio:not([controls]){display:none;height:0}.swagger-ui img{border-style:none}.swagger-ui svg:not(:root){overflow:hidden}.swagger-ui button,.swagger-ui input,.swagger-ui optgroup,.swagger-ui select,.swagger-ui textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}.swagger-ui button,.swagger-ui input{overflow:visible}.swagger-ui button,.swagger-ui select{text-transform:none}.swagger-ui [type=reset],.swagger-ui [type=submit],.swagger-ui button,.swagger-ui html [type=button]{-webkit-appearance:button}.swagger-ui [type=button]::-moz-focus-inner,.swagger-ui [type=reset]::-moz-focus-inner,.swagger-ui [type=submit]::-moz-focus-inner,.swagger-ui button::-moz-focus-inner{border-style:none;padding:0}.swagger-ui [type=button]:-moz-focusring,.swagger-ui [type=reset]:-moz-focusring,.swagger-ui [type=submit]:-moz-focusring,.swagger-ui button:-moz-focusring{outline:1px dotted ButtonText}.swagger-ui fieldset{padding:.35em .75em .625em}.swagger-ui legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}.swagger-ui progress{display:inline-block;vertical-align:baseline}.swagger-ui textarea{overflow:auto}.swagger-ui [type=checkbox],.swagger-ui [type=radio]{box-sizing:border-box;padding:0}.swagger-ui [type=number]::-webkit-inner-spin-button,.swagger-ui [type=number]::-webkit-outer-spin-button{height:auto}.swagger-ui [type=search]{-webkit-appearance:textfield;outline-offset:-2px}.swagger-ui [type=search]::-webkit-search-cancel-button,.swagger-ui [type=search]::-webkit-search-decoration{-webkit-appearance:none}.swagger-ui ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.swagger-ui details,.swagger-ui menu{display:block}.swagger-ui summary{display:list-item}.swagger-ui canvas{display:inline-block}.swagger-ui [hidden],.swagger-ui template{display:none}.swagger-ui .debug *{outline:1px solid gold}.swagger-ui .debug-white *{outline:1px solid #fff}.swagger-ui .debug-black *{outline:1px solid #000}.swagger-ui .debug-grid{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTRDOTY4N0U2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTRDOTY4N0Q2N0VFMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3NjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3NzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsBS+GMAAAAjSURBVHjaYvz//z8DLsD4gcGXiYEAGBIKGBne//fFpwAgwAB98AaF2pjlUQAAAABJRU5ErkJggg==) repeat 0 0}.swagger-ui .debug-grid-16{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODYyRjhERDU2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODYyRjhERDQ2N0YyMTFFNjg2MzZDQjkwNkQ4MjgwMEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QTY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3QjY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvCS01IAAABMSURBVHjaYmR4/5+BFPBfAMFm/MBgx8RAGWCn1AAmSg34Q6kBDKMGMDCwICeMIemF/5QawEipAWwUhwEjMDvbAWlWkvVBwu8vQIABAEwBCph8U6c0AAAAAElFTkSuQmCC) repeat 0 0}.swagger-ui .debug-grid-8-solid{background:#fff url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAAAAD/4QMxaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIxMjI0OTczNjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIxMjI0OTc0NjdCMzExRTZCMkJDRTI0MDgxMDAyMTcxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjEyMjQ5NzE2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjEyMjQ5NzI2N0IzMTFFNkIyQkNFMjQwODEwMDIxNzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAbGhopHSlBJiZBQi8vL0JHPz4+P0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHAR0pKTQmND8oKD9HPzU/R0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0f/wAARCAAIAAgDASIAAhEBAxEB/8QAWQABAQAAAAAAAAAAAAAAAAAAAAYBAQEAAAAAAAAAAAAAAAAAAAIEEAEBAAMBAAAAAAAAAAAAAAABADECA0ERAAEDBQAAAAAAAAAAAAAAAAARITFBUWESIv/aAAwDAQACEQMRAD8AoOnTV1QTD7JJshP3vSM3P//Z) repeat 0 0}.swagger-ui .debug-grid-16-solid{background:#fff url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzY3MkJEN0U2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzY3MkJEN0Y2N0M1MTFFNkIyQkNFMjQwODEwMDIxNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NjcyQkQ3QzY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NjcyQkQ3RDY3QzUxMUU2QjJCQ0UyNDA4MTAwMjE3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pve6J3kAAAAzSURBVHjaYvz//z8D0UDsMwMjSRoYP5Gq4SPNbRjVMEQ1fCRDg+in/6+J1AJUxsgAEGAA31BAJMS0GYEAAAAASUVORK5CYII=) repeat 0 0}.swagger-ui .border-box,.swagger-ui a,.swagger-ui article,.swagger-ui body,.swagger-ui code,.swagger-ui dd,.swagger-ui div,.swagger-ui dl,.swagger-ui dt,.swagger-ui fieldset,.swagger-ui footer,.swagger-ui form,.swagger-ui h1,.swagger-ui h2,.swagger-ui h3,.swagger-ui h4,.swagger-ui h5,.swagger-ui h6,.swagger-ui header,.swagger-ui html,.swagger-ui input[type=email],.swagger-ui input[type=number],.swagger-ui input[type=password],.swagger-ui input[type=tel],.swagger-ui input[type=text],.swagger-ui input[type=url],.swagger-ui legend,.swagger-ui li,.swagger-ui main,.swagger-ui ol,.swagger-ui p,.swagger-ui pre,.swagger-ui section,.swagger-ui table,.swagger-ui td,.swagger-ui textarea,.swagger-ui th,.swagger-ui tr,.swagger-ui ul{box-sizing:border-box}.swagger-ui .aspect-ratio{height:0;position:relative}.swagger-ui .aspect-ratio--16x9{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1{padding-bottom:100%}.swagger-ui .aspect-ratio--object{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}@media screen and (min-width:30em){.swagger-ui .aspect-ratio-ns{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-ns{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-ns{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-ns{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-ns{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-ns{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-ns{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-ns{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-ns{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-ns{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-ns{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-ns{padding-bottom:100%}.swagger-ui .aspect-ratio--object-ns{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .aspect-ratio-m{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-m{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-m{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-m{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-m{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-m{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-m{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-m{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-m{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-m{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-m{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-m{padding-bottom:100%}.swagger-ui .aspect-ratio--object-m{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}@media screen and (min-width:60em){.swagger-ui .aspect-ratio-l{height:0;position:relative}.swagger-ui .aspect-ratio--16x9-l{padding-bottom:56.25%}.swagger-ui .aspect-ratio--9x16-l{padding-bottom:177.77%}.swagger-ui .aspect-ratio--4x3-l{padding-bottom:75%}.swagger-ui .aspect-ratio--3x4-l{padding-bottom:133.33%}.swagger-ui .aspect-ratio--6x4-l{padding-bottom:66.6%}.swagger-ui .aspect-ratio--4x6-l{padding-bottom:150%}.swagger-ui .aspect-ratio--8x5-l{padding-bottom:62.5%}.swagger-ui .aspect-ratio--5x8-l{padding-bottom:160%}.swagger-ui .aspect-ratio--7x5-l{padding-bottom:71.42%}.swagger-ui .aspect-ratio--5x7-l{padding-bottom:140%}.swagger-ui .aspect-ratio--1x1-l{padding-bottom:100%}.swagger-ui .aspect-ratio--object-l{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%;z-index:100}}.swagger-ui img{max-width:100%}.swagger-ui .cover{background-size:cover!important}.swagger-ui .contain{background-size:contain!important}@media screen and (min-width:30em){.swagger-ui .cover-ns{background-size:cover!important}.swagger-ui .contain-ns{background-size:contain!important}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .cover-m{background-size:cover!important}.swagger-ui .contain-m{background-size:contain!important}}@media screen and (min-width:60em){.swagger-ui .cover-l{background-size:cover!important}.swagger-ui .contain-l{background-size:contain!important}}.swagger-ui .bg-center{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left{background-position:0;background-repeat:no-repeat}@media screen and (min-width:30em){.swagger-ui .bg-center-ns{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-ns{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-ns{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-ns{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-ns{background-position:0;background-repeat:no-repeat}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .bg-center-m{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-m{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-m{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-m{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-m{background-position:0;background-repeat:no-repeat}}@media screen and (min-width:60em){.swagger-ui .bg-center-l{background-position:50%;background-repeat:no-repeat}.swagger-ui .bg-top-l{background-position:top;background-repeat:no-repeat}.swagger-ui .bg-right-l{background-position:100%;background-repeat:no-repeat}.swagger-ui .bg-bottom-l{background-position:bottom;background-repeat:no-repeat}.swagger-ui .bg-left-l{background-position:0;background-repeat:no-repeat}}.swagger-ui .outline{outline:1px solid}.swagger-ui .outline-transparent{outline:1px solid transparent}.swagger-ui .outline-0{outline:0}@media screen and (min-width:30em){.swagger-ui .outline-ns{outline:1px solid}.swagger-ui .outline-transparent-ns{outline:1px solid transparent}.swagger-ui .outline-0-ns{outline:0}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .outline-m{outline:1px solid}.swagger-ui .outline-transparent-m{outline:1px solid transparent}.swagger-ui .outline-0-m{outline:0}}@media screen and (min-width:60em){.swagger-ui .outline-l{outline:1px solid}.swagger-ui .outline-transparent-l{outline:1px solid transparent}.swagger-ui .outline-0-l{outline:0}}.swagger-ui .ba{border-style:solid;border-width:1px}.swagger-ui .bt{border-top-style:solid;border-top-width:1px}.swagger-ui .br{border-right-style:solid;border-right-width:1px}.swagger-ui .bb{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl{border-left-style:solid;border-left-width:1px}.swagger-ui .bn{border-style:none;border-width:0}@media screen and (min-width:30em){.swagger-ui .ba-ns{border-style:solid;border-width:1px}.swagger-ui .bt-ns{border-top-style:solid;border-top-width:1px}.swagger-ui .br-ns{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-ns{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-ns{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-ns{border-style:none;border-width:0}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .ba-m{border-style:solid;border-width:1px}.swagger-ui .bt-m{border-top-style:solid;border-top-width:1px}.swagger-ui .br-m{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-m{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-m{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-m{border-style:none;border-width:0}}@media screen and (min-width:60em){.swagger-ui .ba-l{border-style:solid;border-width:1px}.swagger-ui .bt-l{border-top-style:solid;border-top-width:1px}.swagger-ui .br-l{border-right-style:solid;border-right-width:1px}.swagger-ui .bb-l{border-bottom-style:solid;border-bottom-width:1px}.swagger-ui .bl-l{border-left-style:solid;border-left-width:1px}.swagger-ui .bn-l{border-style:none;border-width:0}}.swagger-ui .b--black{border-color:#000}.swagger-ui .b--near-black{border-color:#111}.swagger-ui .b--dark-gray{border-color:#333}.swagger-ui .b--mid-gray{border-color:#555}.swagger-ui .b--gray{border-color:#777}.swagger-ui .b--silver{border-color:#999}.swagger-ui .b--light-silver{border-color:#aaa}.swagger-ui .b--moon-gray{border-color:#ccc}.swagger-ui .b--light-gray{border-color:#eee}.swagger-ui .b--near-white{border-color:#f4f4f4}.swagger-ui .b--white{border-color:#fff}.swagger-ui .b--white-90{border-color:hsla(0,0%,100%,.9)}.swagger-ui .b--white-80{border-color:hsla(0,0%,100%,.8)}.swagger-ui .b--white-70{border-color:hsla(0,0%,100%,.7)}.swagger-ui .b--white-60{border-color:hsla(0,0%,100%,.6)}.swagger-ui .b--white-50{border-color:hsla(0,0%,100%,.5)}.swagger-ui .b--white-40{border-color:hsla(0,0%,100%,.4)}.swagger-ui .b--white-30{border-color:hsla(0,0%,100%,.3)}.swagger-ui .b--white-20{border-color:hsla(0,0%,100%,.2)}.swagger-ui .b--white-10{border-color:hsla(0,0%,100%,.1)}.swagger-ui .b--white-05{border-color:hsla(0,0%,100%,.05)}.swagger-ui .b--white-025{border-color:hsla(0,0%,100%,.025)}.swagger-ui .b--white-0125{border-color:hsla(0,0%,100%,.013)}.swagger-ui .b--black-90{border-color:rgba(0,0,0,.9)}.swagger-ui .b--black-80{border-color:rgba(0,0,0,.8)}.swagger-ui .b--black-70{border-color:rgba(0,0,0,.7)}.swagger-ui .b--black-60{border-color:rgba(0,0,0,.6)}.swagger-ui .b--black-50{border-color:rgba(0,0,0,.5)}.swagger-ui .b--black-40{border-color:rgba(0,0,0,.4)}.swagger-ui .b--black-30{border-color:rgba(0,0,0,.3)}.swagger-ui .b--black-20{border-color:rgba(0,0,0,.2)}.swagger-ui .b--black-10{border-color:rgba(0,0,0,.1)}.swagger-ui .b--black-05{border-color:rgba(0,0,0,.05)}.swagger-ui .b--black-025{border-color:rgba(0,0,0,.025)}.swagger-ui .b--black-0125{border-color:rgba(0,0,0,.013)}.swagger-ui .b--dark-red{border-color:#e7040f}.swagger-ui .b--red{border-color:#ff4136}.swagger-ui .b--light-red{border-color:#ff725c}.swagger-ui .b--orange{border-color:#ff6300}.swagger-ui .b--gold{border-color:#ffb700}.swagger-ui .b--yellow{border-color:gold}.swagger-ui .b--light-yellow{border-color:#fbf1a9}.swagger-ui .b--purple{border-color:#5e2ca5}.swagger-ui .b--light-purple{border-color:#a463f2}.swagger-ui .b--dark-pink{border-color:#d5008f}.swagger-ui .b--hot-pink{border-color:#ff41b4}.swagger-ui .b--pink{border-color:#ff80cc}.swagger-ui .b--light-pink{border-color:#ffa3d7}.swagger-ui .b--dark-green{border-color:#137752}.swagger-ui .b--green{border-color:#19a974}.swagger-ui .b--light-green{border-color:#9eebcf}.swagger-ui .b--navy{border-color:#001b44}.swagger-ui .b--dark-blue{border-color:#00449e}.swagger-ui .b--blue{border-color:#357edd}.swagger-ui .b--light-blue{border-color:#96ccff}.swagger-ui .b--lightest-blue{border-color:#cdecff}.swagger-ui .b--washed-blue{border-color:#f6fffe}.swagger-ui .b--washed-green{border-color:#e8fdf5}.swagger-ui .b--washed-yellow{border-color:#fffceb}.swagger-ui .b--washed-red{border-color:#ffdfdf}.swagger-ui .b--transparent{border-color:transparent}.swagger-ui .b--inherit{border-color:inherit}.swagger-ui .br0{border-radius:0}.swagger-ui .br1{border-radius:.125rem}.swagger-ui .br2{border-radius:.25rem}.swagger-ui .br3{border-radius:.5rem}.swagger-ui .br4{border-radius:1rem}.swagger-ui .br-100{border-radius:100%}.swagger-ui .br-pill{border-radius:9999px}.swagger-ui .br--bottom{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left{border-bottom-right-radius:0;border-top-right-radius:0}@media screen and (min-width:30em){.swagger-ui .br0-ns{border-radius:0}.swagger-ui .br1-ns{border-radius:.125rem}.swagger-ui .br2-ns{border-radius:.25rem}.swagger-ui .br3-ns{border-radius:.5rem}.swagger-ui .br4-ns{border-radius:1rem}.swagger-ui .br-100-ns{border-radius:100%}.swagger-ui .br-pill-ns{border-radius:9999px}.swagger-ui .br--bottom-ns{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-ns{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-ns{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-ns{border-bottom-right-radius:0;border-top-right-radius:0}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .br0-m{border-radius:0}.swagger-ui .br1-m{border-radius:.125rem}.swagger-ui .br2-m{border-radius:.25rem}.swagger-ui .br3-m{border-radius:.5rem}.swagger-ui .br4-m{border-radius:1rem}.swagger-ui .br-100-m{border-radius:100%}.swagger-ui .br-pill-m{border-radius:9999px}.swagger-ui .br--bottom-m{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-m{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-m{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-m{border-bottom-right-radius:0;border-top-right-radius:0}}@media screen and (min-width:60em){.swagger-ui .br0-l{border-radius:0}.swagger-ui .br1-l{border-radius:.125rem}.swagger-ui .br2-l{border-radius:.25rem}.swagger-ui .br3-l{border-radius:.5rem}.swagger-ui .br4-l{border-radius:1rem}.swagger-ui .br-100-l{border-radius:100%}.swagger-ui .br-pill-l{border-radius:9999px}.swagger-ui .br--bottom-l{border-top-left-radius:0;border-top-right-radius:0}.swagger-ui .br--top-l{border-bottom-left-radius:0;border-bottom-right-radius:0}.swagger-ui .br--right-l{border-bottom-left-radius:0;border-top-left-radius:0}.swagger-ui .br--left-l{border-bottom-right-radius:0;border-top-right-radius:0}}.swagger-ui .b--dotted{border-style:dotted}.swagger-ui .b--dashed{border-style:dashed}.swagger-ui .b--solid{border-style:solid}.swagger-ui .b--none{border-style:none}@media screen and (min-width:30em){.swagger-ui .b--dotted-ns{border-style:dotted}.swagger-ui .b--dashed-ns{border-style:dashed}.swagger-ui .b--solid-ns{border-style:solid}.swagger-ui .b--none-ns{border-style:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .b--dotted-m{border-style:dotted}.swagger-ui .b--dashed-m{border-style:dashed}.swagger-ui .b--solid-m{border-style:solid}.swagger-ui .b--none-m{border-style:none}}@media screen and (min-width:60em){.swagger-ui .b--dotted-l{border-style:dotted}.swagger-ui .b--dashed-l{border-style:dashed}.swagger-ui .b--solid-l{border-style:solid}.swagger-ui .b--none-l{border-style:none}}.swagger-ui .bw0{border-width:0}.swagger-ui .bw1{border-width:.125rem}.swagger-ui .bw2{border-width:.25rem}.swagger-ui .bw3{border-width:.5rem}.swagger-ui .bw4{border-width:1rem}.swagger-ui .bw5{border-width:2rem}.swagger-ui .bt-0{border-top-width:0}.swagger-ui .br-0{border-right-width:0}.swagger-ui .bb-0{border-bottom-width:0}.swagger-ui .bl-0{border-left-width:0}@media screen and (min-width:30em){.swagger-ui .bw0-ns{border-width:0}.swagger-ui .bw1-ns{border-width:.125rem}.swagger-ui .bw2-ns{border-width:.25rem}.swagger-ui .bw3-ns{border-width:.5rem}.swagger-ui .bw4-ns{border-width:1rem}.swagger-ui .bw5-ns{border-width:2rem}.swagger-ui .bt-0-ns{border-top-width:0}.swagger-ui .br-0-ns{border-right-width:0}.swagger-ui .bb-0-ns{border-bottom-width:0}.swagger-ui .bl-0-ns{border-left-width:0}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .bw0-m{border-width:0}.swagger-ui .bw1-m{border-width:.125rem}.swagger-ui .bw2-m{border-width:.25rem}.swagger-ui .bw3-m{border-width:.5rem}.swagger-ui .bw4-m{border-width:1rem}.swagger-ui .bw5-m{border-width:2rem}.swagger-ui .bt-0-m{border-top-width:0}.swagger-ui .br-0-m{border-right-width:0}.swagger-ui .bb-0-m{border-bottom-width:0}.swagger-ui .bl-0-m{border-left-width:0}}@media screen and (min-width:60em){.swagger-ui .bw0-l{border-width:0}.swagger-ui .bw1-l{border-width:.125rem}.swagger-ui .bw2-l{border-width:.25rem}.swagger-ui .bw3-l{border-width:.5rem}.swagger-ui .bw4-l{border-width:1rem}.swagger-ui .bw5-l{border-width:2rem}.swagger-ui .bt-0-l{border-top-width:0}.swagger-ui .br-0-l{border-right-width:0}.swagger-ui .bb-0-l{border-bottom-width:0}.swagger-ui .bl-0-l{border-left-width:0}}.swagger-ui .shadow-1{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}@media screen and (min-width:30em){.swagger-ui .shadow-1-ns{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-ns{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-ns{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-ns{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-ns{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .shadow-1-m{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-m{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-m{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-m{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-m{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}@media screen and (min-width:60em){.swagger-ui .shadow-1-l{box-shadow:0 0 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-2-l{box-shadow:0 0 8px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-3-l{box-shadow:2px 2px 4px 2px rgba(0,0,0,.2)}.swagger-ui .shadow-4-l{box-shadow:2px 2px 8px 0 rgba(0,0,0,.2)}.swagger-ui .shadow-5-l{box-shadow:4px 4px 8px 0 rgba(0,0,0,.2)}}.swagger-ui .pre{overflow-x:auto;overflow-y:hidden;overflow:scroll}.swagger-ui .top-0{top:0}.swagger-ui .right-0{right:0}.swagger-ui .bottom-0{bottom:0}.swagger-ui .left-0{left:0}.swagger-ui .top-1{top:1rem}.swagger-ui .right-1{right:1rem}.swagger-ui .bottom-1{bottom:1rem}.swagger-ui .left-1{left:1rem}.swagger-ui .top-2{top:2rem}.swagger-ui .right-2{right:2rem}.swagger-ui .bottom-2{bottom:2rem}.swagger-ui .left-2{left:2rem}.swagger-ui .top--1{top:-1rem}.swagger-ui .right--1{right:-1rem}.swagger-ui .bottom--1{bottom:-1rem}.swagger-ui .left--1{left:-1rem}.swagger-ui .top--2{top:-2rem}.swagger-ui .right--2{right:-2rem}.swagger-ui .bottom--2{bottom:-2rem}.swagger-ui .left--2{left:-2rem}.swagger-ui .absolute--fill{bottom:0;left:0;right:0;top:0}@media screen and (min-width:30em){.swagger-ui .top-0-ns{top:0}.swagger-ui .left-0-ns{left:0}.swagger-ui .right-0-ns{right:0}.swagger-ui .bottom-0-ns{bottom:0}.swagger-ui .top-1-ns{top:1rem}.swagger-ui .left-1-ns{left:1rem}.swagger-ui .right-1-ns{right:1rem}.swagger-ui .bottom-1-ns{bottom:1rem}.swagger-ui .top-2-ns{top:2rem}.swagger-ui .left-2-ns{left:2rem}.swagger-ui .right-2-ns{right:2rem}.swagger-ui .bottom-2-ns{bottom:2rem}.swagger-ui .top--1-ns{top:-1rem}.swagger-ui .right--1-ns{right:-1rem}.swagger-ui .bottom--1-ns{bottom:-1rem}.swagger-ui .left--1-ns{left:-1rem}.swagger-ui .top--2-ns{top:-2rem}.swagger-ui .right--2-ns{right:-2rem}.swagger-ui .bottom--2-ns{bottom:-2rem}.swagger-ui .left--2-ns{left:-2rem}.swagger-ui .absolute--fill-ns{bottom:0;left:0;right:0;top:0}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .top-0-m{top:0}.swagger-ui .left-0-m{left:0}.swagger-ui .right-0-m{right:0}.swagger-ui .bottom-0-m{bottom:0}.swagger-ui .top-1-m{top:1rem}.swagger-ui .left-1-m{left:1rem}.swagger-ui .right-1-m{right:1rem}.swagger-ui .bottom-1-m{bottom:1rem}.swagger-ui .top-2-m{top:2rem}.swagger-ui .left-2-m{left:2rem}.swagger-ui .right-2-m{right:2rem}.swagger-ui .bottom-2-m{bottom:2rem}.swagger-ui .top--1-m{top:-1rem}.swagger-ui .right--1-m{right:-1rem}.swagger-ui .bottom--1-m{bottom:-1rem}.swagger-ui .left--1-m{left:-1rem}.swagger-ui .top--2-m{top:-2rem}.swagger-ui .right--2-m{right:-2rem}.swagger-ui .bottom--2-m{bottom:-2rem}.swagger-ui .left--2-m{left:-2rem}.swagger-ui .absolute--fill-m{bottom:0;left:0;right:0;top:0}}@media screen and (min-width:60em){.swagger-ui .top-0-l{top:0}.swagger-ui .left-0-l{left:0}.swagger-ui .right-0-l{right:0}.swagger-ui .bottom-0-l{bottom:0}.swagger-ui .top-1-l{top:1rem}.swagger-ui .left-1-l{left:1rem}.swagger-ui .right-1-l{right:1rem}.swagger-ui .bottom-1-l{bottom:1rem}.swagger-ui .top-2-l{top:2rem}.swagger-ui .left-2-l{left:2rem}.swagger-ui .right-2-l{right:2rem}.swagger-ui .bottom-2-l{bottom:2rem}.swagger-ui .top--1-l{top:-1rem}.swagger-ui .right--1-l{right:-1rem}.swagger-ui .bottom--1-l{bottom:-1rem}.swagger-ui .left--1-l{left:-1rem}.swagger-ui .top--2-l{top:-2rem}.swagger-ui .right--2-l{right:-2rem}.swagger-ui .bottom--2-l{bottom:-2rem}.swagger-ui .left--2-l{left:-2rem}.swagger-ui .absolute--fill-l{bottom:0;left:0;right:0;top:0}}.swagger-ui .cf:after,.swagger-ui .cf:before{content:" ";display:table}.swagger-ui .cf:after{clear:both}.swagger-ui .cf{zoom:1}.swagger-ui .cl{clear:left}.swagger-ui .cr{clear:right}.swagger-ui .cb{clear:both}.swagger-ui .cn{clear:none}@media screen and (min-width:30em){.swagger-ui .cl-ns{clear:left}.swagger-ui .cr-ns{clear:right}.swagger-ui .cb-ns{clear:both}.swagger-ui .cn-ns{clear:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .cl-m{clear:left}.swagger-ui .cr-m{clear:right}.swagger-ui .cb-m{clear:both}.swagger-ui .cn-m{clear:none}}@media screen and (min-width:60em){.swagger-ui .cl-l{clear:left}.swagger-ui .cr-l{clear:right}.swagger-ui .cb-l{clear:both}.swagger-ui .cn-l{clear:none}}.swagger-ui .flex{display:flex}.swagger-ui .inline-flex{display:inline-flex}.swagger-ui .flex-auto{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none{flex:none}.swagger-ui .flex-column{flex-direction:column}.swagger-ui .flex-row{flex-direction:row}.swagger-ui .flex-wrap{flex-wrap:wrap}.swagger-ui .flex-nowrap{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse{flex-direction:column-reverse}.swagger-ui .flex-row-reverse{flex-direction:row-reverse}.swagger-ui .items-start{align-items:flex-start}.swagger-ui .items-end{align-items:flex-end}.swagger-ui .items-center{align-items:center}.swagger-ui .items-baseline{align-items:baseline}.swagger-ui .items-stretch{align-items:stretch}.swagger-ui .self-start{align-self:flex-start}.swagger-ui .self-end{align-self:flex-end}.swagger-ui .self-center{align-self:center}.swagger-ui .self-baseline{align-self:baseline}.swagger-ui .self-stretch{align-self:stretch}.swagger-ui .justify-start{justify-content:flex-start}.swagger-ui .justify-end{justify-content:flex-end}.swagger-ui .justify-center{justify-content:center}.swagger-ui .justify-between{justify-content:space-between}.swagger-ui .justify-around{justify-content:space-around}.swagger-ui .content-start{align-content:flex-start}.swagger-ui .content-end{align-content:flex-end}.swagger-ui .content-center{align-content:center}.swagger-ui .content-between{align-content:space-between}.swagger-ui .content-around{align-content:space-around}.swagger-ui .content-stretch{align-content:stretch}.swagger-ui .order-0{order:0}.swagger-ui .order-1{order:1}.swagger-ui .order-2{order:2}.swagger-ui .order-3{order:3}.swagger-ui .order-4{order:4}.swagger-ui .order-5{order:5}.swagger-ui .order-6{order:6}.swagger-ui .order-7{order:7}.swagger-ui .order-8{order:8}.swagger-ui .order-last{order:99999}.swagger-ui .flex-grow-0{flex-grow:0}.swagger-ui .flex-grow-1{flex-grow:1}.swagger-ui .flex-shrink-0{flex-shrink:0}.swagger-ui .flex-shrink-1{flex-shrink:1}@media screen and (min-width:30em){.swagger-ui .flex-ns{display:flex}.swagger-ui .inline-flex-ns{display:inline-flex}.swagger-ui .flex-auto-ns{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-ns{flex:none}.swagger-ui .flex-column-ns{flex-direction:column}.swagger-ui .flex-row-ns{flex-direction:row}.swagger-ui .flex-wrap-ns{flex-wrap:wrap}.swagger-ui .flex-nowrap-ns{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-ns{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-ns{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-ns{flex-direction:row-reverse}.swagger-ui .items-start-ns{align-items:flex-start}.swagger-ui .items-end-ns{align-items:flex-end}.swagger-ui .items-center-ns{align-items:center}.swagger-ui .items-baseline-ns{align-items:baseline}.swagger-ui .items-stretch-ns{align-items:stretch}.swagger-ui .self-start-ns{align-self:flex-start}.swagger-ui .self-end-ns{align-self:flex-end}.swagger-ui .self-center-ns{align-self:center}.swagger-ui .self-baseline-ns{align-self:baseline}.swagger-ui .self-stretch-ns{align-self:stretch}.swagger-ui .justify-start-ns{justify-content:flex-start}.swagger-ui .justify-end-ns{justify-content:flex-end}.swagger-ui .justify-center-ns{justify-content:center}.swagger-ui .justify-between-ns{justify-content:space-between}.swagger-ui .justify-around-ns{justify-content:space-around}.swagger-ui .content-start-ns{align-content:flex-start}.swagger-ui .content-end-ns{align-content:flex-end}.swagger-ui .content-center-ns{align-content:center}.swagger-ui .content-between-ns{align-content:space-between}.swagger-ui .content-around-ns{align-content:space-around}.swagger-ui .content-stretch-ns{align-content:stretch}.swagger-ui .order-0-ns{order:0}.swagger-ui .order-1-ns{order:1}.swagger-ui .order-2-ns{order:2}.swagger-ui .order-3-ns{order:3}.swagger-ui .order-4-ns{order:4}.swagger-ui .order-5-ns{order:5}.swagger-ui .order-6-ns{order:6}.swagger-ui .order-7-ns{order:7}.swagger-ui .order-8-ns{order:8}.swagger-ui .order-last-ns{order:99999}.swagger-ui .flex-grow-0-ns{flex-grow:0}.swagger-ui .flex-grow-1-ns{flex-grow:1}.swagger-ui .flex-shrink-0-ns{flex-shrink:0}.swagger-ui .flex-shrink-1-ns{flex-shrink:1}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .flex-m{display:flex}.swagger-ui .inline-flex-m{display:inline-flex}.swagger-ui .flex-auto-m{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-m{flex:none}.swagger-ui .flex-column-m{flex-direction:column}.swagger-ui .flex-row-m{flex-direction:row}.swagger-ui .flex-wrap-m{flex-wrap:wrap}.swagger-ui .flex-nowrap-m{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-m{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-m{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-m{flex-direction:row-reverse}.swagger-ui .items-start-m{align-items:flex-start}.swagger-ui .items-end-m{align-items:flex-end}.swagger-ui .items-center-m{align-items:center}.swagger-ui .items-baseline-m{align-items:baseline}.swagger-ui .items-stretch-m{align-items:stretch}.swagger-ui .self-start-m{align-self:flex-start}.swagger-ui .self-end-m{align-self:flex-end}.swagger-ui .self-center-m{align-self:center}.swagger-ui .self-baseline-m{align-self:baseline}.swagger-ui .self-stretch-m{align-self:stretch}.swagger-ui .justify-start-m{justify-content:flex-start}.swagger-ui .justify-end-m{justify-content:flex-end}.swagger-ui .justify-center-m{justify-content:center}.swagger-ui .justify-between-m{justify-content:space-between}.swagger-ui .justify-around-m{justify-content:space-around}.swagger-ui .content-start-m{align-content:flex-start}.swagger-ui .content-end-m{align-content:flex-end}.swagger-ui .content-center-m{align-content:center}.swagger-ui .content-between-m{align-content:space-between}.swagger-ui .content-around-m{align-content:space-around}.swagger-ui .content-stretch-m{align-content:stretch}.swagger-ui .order-0-m{order:0}.swagger-ui .order-1-m{order:1}.swagger-ui .order-2-m{order:2}.swagger-ui .order-3-m{order:3}.swagger-ui .order-4-m{order:4}.swagger-ui .order-5-m{order:5}.swagger-ui .order-6-m{order:6}.swagger-ui .order-7-m{order:7}.swagger-ui .order-8-m{order:8}.swagger-ui .order-last-m{order:99999}.swagger-ui .flex-grow-0-m{flex-grow:0}.swagger-ui .flex-grow-1-m{flex-grow:1}.swagger-ui .flex-shrink-0-m{flex-shrink:0}.swagger-ui .flex-shrink-1-m{flex-shrink:1}}@media screen and (min-width:60em){.swagger-ui .flex-l{display:flex}.swagger-ui .inline-flex-l{display:inline-flex}.swagger-ui .flex-auto-l{flex:1 1 auto;min-height:0;min-width:0}.swagger-ui .flex-none-l{flex:none}.swagger-ui .flex-column-l{flex-direction:column}.swagger-ui .flex-row-l{flex-direction:row}.swagger-ui .flex-wrap-l{flex-wrap:wrap}.swagger-ui .flex-nowrap-l{flex-wrap:nowrap}.swagger-ui .flex-wrap-reverse-l{flex-wrap:wrap-reverse}.swagger-ui .flex-column-reverse-l{flex-direction:column-reverse}.swagger-ui .flex-row-reverse-l{flex-direction:row-reverse}.swagger-ui .items-start-l{align-items:flex-start}.swagger-ui .items-end-l{align-items:flex-end}.swagger-ui .items-center-l{align-items:center}.swagger-ui .items-baseline-l{align-items:baseline}.swagger-ui .items-stretch-l{align-items:stretch}.swagger-ui .self-start-l{align-self:flex-start}.swagger-ui .self-end-l{align-self:flex-end}.swagger-ui .self-center-l{align-self:center}.swagger-ui .self-baseline-l{align-self:baseline}.swagger-ui .self-stretch-l{align-self:stretch}.swagger-ui .justify-start-l{justify-content:flex-start}.swagger-ui .justify-end-l{justify-content:flex-end}.swagger-ui .justify-center-l{justify-content:center}.swagger-ui .justify-between-l{justify-content:space-between}.swagger-ui .justify-around-l{justify-content:space-around}.swagger-ui .content-start-l{align-content:flex-start}.swagger-ui .content-end-l{align-content:flex-end}.swagger-ui .content-center-l{align-content:center}.swagger-ui .content-between-l{align-content:space-between}.swagger-ui .content-around-l{align-content:space-around}.swagger-ui .content-stretch-l{align-content:stretch}.swagger-ui .order-0-l{order:0}.swagger-ui .order-1-l{order:1}.swagger-ui .order-2-l{order:2}.swagger-ui .order-3-l{order:3}.swagger-ui .order-4-l{order:4}.swagger-ui .order-5-l{order:5}.swagger-ui .order-6-l{order:6}.swagger-ui .order-7-l{order:7}.swagger-ui .order-8-l{order:8}.swagger-ui .order-last-l{order:99999}.swagger-ui .flex-grow-0-l{flex-grow:0}.swagger-ui .flex-grow-1-l{flex-grow:1}.swagger-ui .flex-shrink-0-l{flex-shrink:0}.swagger-ui .flex-shrink-1-l{flex-shrink:1}}.swagger-ui .dn{display:none}.swagger-ui .di{display:inline}.swagger-ui .db{display:block}.swagger-ui .dib{display:inline-block}.swagger-ui .dit{display:inline-table}.swagger-ui .dt{display:table}.swagger-ui .dtc{display:table-cell}.swagger-ui .dt-row{display:table-row}.swagger-ui .dt-row-group{display:table-row-group}.swagger-ui .dt-column{display:table-column}.swagger-ui .dt-column-group{display:table-column-group}.swagger-ui .dt--fixed{table-layout:fixed;width:100%}@media screen and (min-width:30em){.swagger-ui .dn-ns{display:none}.swagger-ui .di-ns{display:inline}.swagger-ui .db-ns{display:block}.swagger-ui .dib-ns{display:inline-block}.swagger-ui .dit-ns{display:inline-table}.swagger-ui .dt-ns{display:table}.swagger-ui .dtc-ns{display:table-cell}.swagger-ui .dt-row-ns{display:table-row}.swagger-ui .dt-row-group-ns{display:table-row-group}.swagger-ui .dt-column-ns{display:table-column}.swagger-ui .dt-column-group-ns{display:table-column-group}.swagger-ui .dt--fixed-ns{table-layout:fixed;width:100%}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .dn-m{display:none}.swagger-ui .di-m{display:inline}.swagger-ui .db-m{display:block}.swagger-ui .dib-m{display:inline-block}.swagger-ui .dit-m{display:inline-table}.swagger-ui .dt-m{display:table}.swagger-ui .dtc-m{display:table-cell}.swagger-ui .dt-row-m{display:table-row}.swagger-ui .dt-row-group-m{display:table-row-group}.swagger-ui .dt-column-m{display:table-column}.swagger-ui .dt-column-group-m{display:table-column-group}.swagger-ui .dt--fixed-m{table-layout:fixed;width:100%}}@media screen and (min-width:60em){.swagger-ui .dn-l{display:none}.swagger-ui .di-l{display:inline}.swagger-ui .db-l{display:block}.swagger-ui .dib-l{display:inline-block}.swagger-ui .dit-l{display:inline-table}.swagger-ui .dt-l{display:table}.swagger-ui .dtc-l{display:table-cell}.swagger-ui .dt-row-l{display:table-row}.swagger-ui .dt-row-group-l{display:table-row-group}.swagger-ui .dt-column-l{display:table-column}.swagger-ui .dt-column-group-l{display:table-column-group}.swagger-ui .dt--fixed-l{table-layout:fixed;width:100%}}.swagger-ui .fl{_display:inline;float:left}.swagger-ui .fr{_display:inline;float:right}.swagger-ui .fn{float:none}@media screen and (min-width:30em){.swagger-ui .fl-ns{_display:inline;float:left}.swagger-ui .fr-ns{_display:inline;float:right}.swagger-ui .fn-ns{float:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .fl-m{_display:inline;float:left}.swagger-ui .fr-m{_display:inline;float:right}.swagger-ui .fn-m{float:none}}@media screen and (min-width:60em){.swagger-ui .fl-l{_display:inline;float:left}.swagger-ui .fr-l{_display:inline;float:right}.swagger-ui .fn-l{float:none}}.swagger-ui .sans-serif{font-family:-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica,helvetica neue,ubuntu,roboto,noto,segoe ui,arial,sans-serif}.swagger-ui .serif{font-family:georgia,serif}.swagger-ui .system-sans-serif{font-family:sans-serif}.swagger-ui .system-serif{font-family:serif}.swagger-ui .code,.swagger-ui code{font-family:Consolas,monaco,monospace}.swagger-ui .courier{font-family:Courier Next,courier,monospace}.swagger-ui .helvetica{font-family:helvetica neue,helvetica,sans-serif}.swagger-ui .avenir{font-family:avenir next,avenir,sans-serif}.swagger-ui .athelas{font-family:athelas,georgia,serif}.swagger-ui .georgia{font-family:georgia,serif}.swagger-ui .times{font-family:times,serif}.swagger-ui .bodoni{font-family:Bodoni MT,serif}.swagger-ui .calisto{font-family:Calisto MT,serif}.swagger-ui .garamond{font-family:garamond,serif}.swagger-ui .baskerville{font-family:baskerville,serif}.swagger-ui .i{font-style:italic}.swagger-ui .fs-normal{font-style:normal}@media screen and (min-width:30em){.swagger-ui .i-ns{font-style:italic}.swagger-ui .fs-normal-ns{font-style:normal}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .i-m{font-style:italic}.swagger-ui .fs-normal-m{font-style:normal}}@media screen and (min-width:60em){.swagger-ui .i-l{font-style:italic}.swagger-ui .fs-normal-l{font-style:normal}}.swagger-ui .normal{font-weight:400}.swagger-ui .b{font-weight:700}.swagger-ui .fw1{font-weight:100}.swagger-ui .fw2{font-weight:200}.swagger-ui .fw3{font-weight:300}.swagger-ui .fw4{font-weight:400}.swagger-ui .fw5{font-weight:500}.swagger-ui .fw6{font-weight:600}.swagger-ui .fw7{font-weight:700}.swagger-ui .fw8{font-weight:800}.swagger-ui .fw9{font-weight:900}@media screen and (min-width:30em){.swagger-ui .normal-ns{font-weight:400}.swagger-ui .b-ns{font-weight:700}.swagger-ui .fw1-ns{font-weight:100}.swagger-ui .fw2-ns{font-weight:200}.swagger-ui .fw3-ns{font-weight:300}.swagger-ui .fw4-ns{font-weight:400}.swagger-ui .fw5-ns{font-weight:500}.swagger-ui .fw6-ns{font-weight:600}.swagger-ui .fw7-ns{font-weight:700}.swagger-ui .fw8-ns{font-weight:800}.swagger-ui .fw9-ns{font-weight:900}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .normal-m{font-weight:400}.swagger-ui .b-m{font-weight:700}.swagger-ui .fw1-m{font-weight:100}.swagger-ui .fw2-m{font-weight:200}.swagger-ui .fw3-m{font-weight:300}.swagger-ui .fw4-m{font-weight:400}.swagger-ui .fw5-m{font-weight:500}.swagger-ui .fw6-m{font-weight:600}.swagger-ui .fw7-m{font-weight:700}.swagger-ui .fw8-m{font-weight:800}.swagger-ui .fw9-m{font-weight:900}}@media screen and (min-width:60em){.swagger-ui .normal-l{font-weight:400}.swagger-ui .b-l{font-weight:700}.swagger-ui .fw1-l{font-weight:100}.swagger-ui .fw2-l{font-weight:200}.swagger-ui .fw3-l{font-weight:300}.swagger-ui .fw4-l{font-weight:400}.swagger-ui .fw5-l{font-weight:500}.swagger-ui .fw6-l{font-weight:600}.swagger-ui .fw7-l{font-weight:700}.swagger-ui .fw8-l{font-weight:800}.swagger-ui .fw9-l{font-weight:900}}.swagger-ui .input-reset{-webkit-appearance:none;-moz-appearance:none}.swagger-ui .button-reset::-moz-focus-inner,.swagger-ui .input-reset::-moz-focus-inner{border:0;padding:0}.swagger-ui .h1{height:1rem}.swagger-ui .h2{height:2rem}.swagger-ui .h3{height:4rem}.swagger-ui .h4{height:8rem}.swagger-ui .h5{height:16rem}.swagger-ui .h-25{height:25%}.swagger-ui .h-50{height:50%}.swagger-ui .h-75{height:75%}.swagger-ui .h-100{height:100%}.swagger-ui .min-h-100{min-height:100%}.swagger-ui .vh-25{height:25vh}.swagger-ui .vh-50{height:50vh}.swagger-ui .vh-75{height:75vh}.swagger-ui .vh-100{height:100vh}.swagger-ui .min-vh-100{min-height:100vh}.swagger-ui .h-auto{height:auto}.swagger-ui .h-inherit{height:inherit}@media screen and (min-width:30em){.swagger-ui .h1-ns{height:1rem}.swagger-ui .h2-ns{height:2rem}.swagger-ui .h3-ns{height:4rem}.swagger-ui .h4-ns{height:8rem}.swagger-ui .h5-ns{height:16rem}.swagger-ui .h-25-ns{height:25%}.swagger-ui .h-50-ns{height:50%}.swagger-ui .h-75-ns{height:75%}.swagger-ui .h-100-ns{height:100%}.swagger-ui .min-h-100-ns{min-height:100%}.swagger-ui .vh-25-ns{height:25vh}.swagger-ui .vh-50-ns{height:50vh}.swagger-ui .vh-75-ns{height:75vh}.swagger-ui .vh-100-ns{height:100vh}.swagger-ui .min-vh-100-ns{min-height:100vh}.swagger-ui .h-auto-ns{height:auto}.swagger-ui .h-inherit-ns{height:inherit}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .h1-m{height:1rem}.swagger-ui .h2-m{height:2rem}.swagger-ui .h3-m{height:4rem}.swagger-ui .h4-m{height:8rem}.swagger-ui .h5-m{height:16rem}.swagger-ui .h-25-m{height:25%}.swagger-ui .h-50-m{height:50%}.swagger-ui .h-75-m{height:75%}.swagger-ui .h-100-m{height:100%}.swagger-ui .min-h-100-m{min-height:100%}.swagger-ui .vh-25-m{height:25vh}.swagger-ui .vh-50-m{height:50vh}.swagger-ui .vh-75-m{height:75vh}.swagger-ui .vh-100-m{height:100vh}.swagger-ui .min-vh-100-m{min-height:100vh}.swagger-ui .h-auto-m{height:auto}.swagger-ui .h-inherit-m{height:inherit}}@media screen and (min-width:60em){.swagger-ui .h1-l{height:1rem}.swagger-ui .h2-l{height:2rem}.swagger-ui .h3-l{height:4rem}.swagger-ui .h4-l{height:8rem}.swagger-ui .h5-l{height:16rem}.swagger-ui .h-25-l{height:25%}.swagger-ui .h-50-l{height:50%}.swagger-ui .h-75-l{height:75%}.swagger-ui .h-100-l{height:100%}.swagger-ui .min-h-100-l{min-height:100%}.swagger-ui .vh-25-l{height:25vh}.swagger-ui .vh-50-l{height:50vh}.swagger-ui .vh-75-l{height:75vh}.swagger-ui .vh-100-l{height:100vh}.swagger-ui .min-vh-100-l{min-height:100vh}.swagger-ui .h-auto-l{height:auto}.swagger-ui .h-inherit-l{height:inherit}}.swagger-ui .tracked{letter-spacing:.1em}.swagger-ui .tracked-tight{letter-spacing:-.05em}.swagger-ui .tracked-mega{letter-spacing:.25em}@media screen and (min-width:30em){.swagger-ui .tracked-ns{letter-spacing:.1em}.swagger-ui .tracked-tight-ns{letter-spacing:-.05em}.swagger-ui .tracked-mega-ns{letter-spacing:.25em}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .tracked-m{letter-spacing:.1em}.swagger-ui .tracked-tight-m{letter-spacing:-.05em}.swagger-ui .tracked-mega-m{letter-spacing:.25em}}@media screen and (min-width:60em){.swagger-ui .tracked-l{letter-spacing:.1em}.swagger-ui .tracked-tight-l{letter-spacing:-.05em}.swagger-ui .tracked-mega-l{letter-spacing:.25em}}.swagger-ui .lh-solid{line-height:1}.swagger-ui .lh-title{line-height:1.25}.swagger-ui .lh-copy{line-height:1.5}@media screen and (min-width:30em){.swagger-ui .lh-solid-ns{line-height:1}.swagger-ui .lh-title-ns{line-height:1.25}.swagger-ui .lh-copy-ns{line-height:1.5}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .lh-solid-m{line-height:1}.swagger-ui .lh-title-m{line-height:1.25}.swagger-ui .lh-copy-m{line-height:1.5}}@media screen and (min-width:60em){.swagger-ui .lh-solid-l{line-height:1}.swagger-ui .lh-title-l{line-height:1.25}.swagger-ui .lh-copy-l{line-height:1.5}}.swagger-ui .link{-webkit-text-decoration:none;text-decoration:none}.swagger-ui .link,.swagger-ui .link:active,.swagger-ui .link:focus,.swagger-ui .link:hover,.swagger-ui .link:link,.swagger-ui .link:visited{transition:color .15s ease-in}.swagger-ui .link:focus{outline:1px dotted currentColor}.swagger-ui .list{list-style-type:none}.swagger-ui .mw-100{max-width:100%}.swagger-ui .mw1{max-width:1rem}.swagger-ui .mw2{max-width:2rem}.swagger-ui .mw3{max-width:4rem}.swagger-ui .mw4{max-width:8rem}.swagger-ui .mw5{max-width:16rem}.swagger-ui .mw6{max-width:32rem}.swagger-ui .mw7{max-width:48rem}.swagger-ui .mw8{max-width:64rem}.swagger-ui .mw9{max-width:96rem}.swagger-ui .mw-none{max-width:none}@media screen and (min-width:30em){.swagger-ui .mw-100-ns{max-width:100%}.swagger-ui .mw1-ns{max-width:1rem}.swagger-ui .mw2-ns{max-width:2rem}.swagger-ui .mw3-ns{max-width:4rem}.swagger-ui .mw4-ns{max-width:8rem}.swagger-ui .mw5-ns{max-width:16rem}.swagger-ui .mw6-ns{max-width:32rem}.swagger-ui .mw7-ns{max-width:48rem}.swagger-ui .mw8-ns{max-width:64rem}.swagger-ui .mw9-ns{max-width:96rem}.swagger-ui .mw-none-ns{max-width:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .mw-100-m{max-width:100%}.swagger-ui .mw1-m{max-width:1rem}.swagger-ui .mw2-m{max-width:2rem}.swagger-ui .mw3-m{max-width:4rem}.swagger-ui .mw4-m{max-width:8rem}.swagger-ui .mw5-m{max-width:16rem}.swagger-ui .mw6-m{max-width:32rem}.swagger-ui .mw7-m{max-width:48rem}.swagger-ui .mw8-m{max-width:64rem}.swagger-ui .mw9-m{max-width:96rem}.swagger-ui .mw-none-m{max-width:none}}@media screen and (min-width:60em){.swagger-ui .mw-100-l{max-width:100%}.swagger-ui .mw1-l{max-width:1rem}.swagger-ui .mw2-l{max-width:2rem}.swagger-ui .mw3-l{max-width:4rem}.swagger-ui .mw4-l{max-width:8rem}.swagger-ui .mw5-l{max-width:16rem}.swagger-ui .mw6-l{max-width:32rem}.swagger-ui .mw7-l{max-width:48rem}.swagger-ui .mw8-l{max-width:64rem}.swagger-ui .mw9-l{max-width:96rem}.swagger-ui .mw-none-l{max-width:none}}.swagger-ui .w1{width:1rem}.swagger-ui .w2{width:2rem}.swagger-ui .w3{width:4rem}.swagger-ui .w4{width:8rem}.swagger-ui .w5{width:16rem}.swagger-ui .w-10{width:10%}.swagger-ui .w-20{width:20%}.swagger-ui .w-25{width:25%}.swagger-ui .w-30{width:30%}.swagger-ui .w-33{width:33%}.swagger-ui .w-34{width:34%}.swagger-ui .w-40{width:40%}.swagger-ui .w-50{width:50%}.swagger-ui .w-60{width:60%}.swagger-ui .w-70{width:70%}.swagger-ui .w-75{width:75%}.swagger-ui .w-80{width:80%}.swagger-ui .w-90{width:90%}.swagger-ui .w-100{width:100%}.swagger-ui .w-third{width:33.3333333333%}.swagger-ui .w-two-thirds{width:66.6666666667%}.swagger-ui .w-auto{width:auto}@media screen and (min-width:30em){.swagger-ui .w1-ns{width:1rem}.swagger-ui .w2-ns{width:2rem}.swagger-ui .w3-ns{width:4rem}.swagger-ui .w4-ns{width:8rem}.swagger-ui .w5-ns{width:16rem}.swagger-ui .w-10-ns{width:10%}.swagger-ui .w-20-ns{width:20%}.swagger-ui .w-25-ns{width:25%}.swagger-ui .w-30-ns{width:30%}.swagger-ui .w-33-ns{width:33%}.swagger-ui .w-34-ns{width:34%}.swagger-ui .w-40-ns{width:40%}.swagger-ui .w-50-ns{width:50%}.swagger-ui .w-60-ns{width:60%}.swagger-ui .w-70-ns{width:70%}.swagger-ui .w-75-ns{width:75%}.swagger-ui .w-80-ns{width:80%}.swagger-ui .w-90-ns{width:90%}.swagger-ui .w-100-ns{width:100%}.swagger-ui .w-third-ns{width:33.3333333333%}.swagger-ui .w-two-thirds-ns{width:66.6666666667%}.swagger-ui .w-auto-ns{width:auto}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .w1-m{width:1rem}.swagger-ui .w2-m{width:2rem}.swagger-ui .w3-m{width:4rem}.swagger-ui .w4-m{width:8rem}.swagger-ui .w5-m{width:16rem}.swagger-ui .w-10-m{width:10%}.swagger-ui .w-20-m{width:20%}.swagger-ui .w-25-m{width:25%}.swagger-ui .w-30-m{width:30%}.swagger-ui .w-33-m{width:33%}.swagger-ui .w-34-m{width:34%}.swagger-ui .w-40-m{width:40%}.swagger-ui .w-50-m{width:50%}.swagger-ui .w-60-m{width:60%}.swagger-ui .w-70-m{width:70%}.swagger-ui .w-75-m{width:75%}.swagger-ui .w-80-m{width:80%}.swagger-ui .w-90-m{width:90%}.swagger-ui .w-100-m{width:100%}.swagger-ui .w-third-m{width:33.3333333333%}.swagger-ui .w-two-thirds-m{width:66.6666666667%}.swagger-ui .w-auto-m{width:auto}}@media screen and (min-width:60em){.swagger-ui .w1-l{width:1rem}.swagger-ui .w2-l{width:2rem}.swagger-ui .w3-l{width:4rem}.swagger-ui .w4-l{width:8rem}.swagger-ui .w5-l{width:16rem}.swagger-ui .w-10-l{width:10%}.swagger-ui .w-20-l{width:20%}.swagger-ui .w-25-l{width:25%}.swagger-ui .w-30-l{width:30%}.swagger-ui .w-33-l{width:33%}.swagger-ui .w-34-l{width:34%}.swagger-ui .w-40-l{width:40%}.swagger-ui .w-50-l{width:50%}.swagger-ui .w-60-l{width:60%}.swagger-ui .w-70-l{width:70%}.swagger-ui .w-75-l{width:75%}.swagger-ui .w-80-l{width:80%}.swagger-ui .w-90-l{width:90%}.swagger-ui .w-100-l{width:100%}.swagger-ui .w-third-l{width:33.3333333333%}.swagger-ui .w-two-thirds-l{width:66.6666666667%}.swagger-ui .w-auto-l{width:auto}}.swagger-ui .overflow-visible{overflow:visible}.swagger-ui .overflow-hidden{overflow:hidden}.swagger-ui .overflow-scroll{overflow:scroll}.swagger-ui .overflow-auto{overflow:auto}.swagger-ui .overflow-x-visible{overflow-x:visible}.swagger-ui .overflow-x-hidden{overflow-x:hidden}.swagger-ui .overflow-x-scroll{overflow-x:scroll}.swagger-ui .overflow-x-auto{overflow-x:auto}.swagger-ui .overflow-y-visible{overflow-y:visible}.swagger-ui .overflow-y-hidden{overflow-y:hidden}.swagger-ui .overflow-y-scroll{overflow-y:scroll}.swagger-ui .overflow-y-auto{overflow-y:auto}@media screen and (min-width:30em){.swagger-ui .overflow-visible-ns{overflow:visible}.swagger-ui .overflow-hidden-ns{overflow:hidden}.swagger-ui .overflow-scroll-ns{overflow:scroll}.swagger-ui .overflow-auto-ns{overflow:auto}.swagger-ui .overflow-x-visible-ns{overflow-x:visible}.swagger-ui .overflow-x-hidden-ns{overflow-x:hidden}.swagger-ui .overflow-x-scroll-ns{overflow-x:scroll}.swagger-ui .overflow-x-auto-ns{overflow-x:auto}.swagger-ui .overflow-y-visible-ns{overflow-y:visible}.swagger-ui .overflow-y-hidden-ns{overflow-y:hidden}.swagger-ui .overflow-y-scroll-ns{overflow-y:scroll}.swagger-ui .overflow-y-auto-ns{overflow-y:auto}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .overflow-visible-m{overflow:visible}.swagger-ui .overflow-hidden-m{overflow:hidden}.swagger-ui .overflow-scroll-m{overflow:scroll}.swagger-ui .overflow-auto-m{overflow:auto}.swagger-ui .overflow-x-visible-m{overflow-x:visible}.swagger-ui .overflow-x-hidden-m{overflow-x:hidden}.swagger-ui .overflow-x-scroll-m{overflow-x:scroll}.swagger-ui .overflow-x-auto-m{overflow-x:auto}.swagger-ui .overflow-y-visible-m{overflow-y:visible}.swagger-ui .overflow-y-hidden-m{overflow-y:hidden}.swagger-ui .overflow-y-scroll-m{overflow-y:scroll}.swagger-ui .overflow-y-auto-m{overflow-y:auto}}@media screen and (min-width:60em){.swagger-ui .overflow-visible-l{overflow:visible}.swagger-ui .overflow-hidden-l{overflow:hidden}.swagger-ui .overflow-scroll-l{overflow:scroll}.swagger-ui .overflow-auto-l{overflow:auto}.swagger-ui .overflow-x-visible-l{overflow-x:visible}.swagger-ui .overflow-x-hidden-l{overflow-x:hidden}.swagger-ui .overflow-x-scroll-l{overflow-x:scroll}.swagger-ui .overflow-x-auto-l{overflow-x:auto}.swagger-ui .overflow-y-visible-l{overflow-y:visible}.swagger-ui .overflow-y-hidden-l{overflow-y:hidden}.swagger-ui .overflow-y-scroll-l{overflow-y:scroll}.swagger-ui .overflow-y-auto-l{overflow-y:auto}}.swagger-ui .static{position:static}.swagger-ui .relative{position:relative}.swagger-ui .absolute{position:absolute}.swagger-ui .fixed{position:fixed}@media screen and (min-width:30em){.swagger-ui .static-ns{position:static}.swagger-ui .relative-ns{position:relative}.swagger-ui .absolute-ns{position:absolute}.swagger-ui .fixed-ns{position:fixed}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .static-m{position:static}.swagger-ui .relative-m{position:relative}.swagger-ui .absolute-m{position:absolute}.swagger-ui .fixed-m{position:fixed}}@media screen and (min-width:60em){.swagger-ui .static-l{position:static}.swagger-ui .relative-l{position:relative}.swagger-ui .absolute-l{position:absolute}.swagger-ui .fixed-l{position:fixed}}.swagger-ui .o-100{opacity:1}.swagger-ui .o-90{opacity:.9}.swagger-ui .o-80{opacity:.8}.swagger-ui .o-70{opacity:.7}.swagger-ui .o-60{opacity:.6}.swagger-ui .o-50{opacity:.5}.swagger-ui .o-40{opacity:.4}.swagger-ui .o-30{opacity:.3}.swagger-ui .o-20{opacity:.2}.swagger-ui .o-10{opacity:.1}.swagger-ui .o-05{opacity:.05}.swagger-ui .o-025{opacity:.025}.swagger-ui .o-0{opacity:0}.swagger-ui .rotate-45{transform:rotate(45deg)}.swagger-ui .rotate-90{transform:rotate(90deg)}.swagger-ui .rotate-135{transform:rotate(135deg)}.swagger-ui .rotate-180{transform:rotate(180deg)}.swagger-ui .rotate-225{transform:rotate(225deg)}.swagger-ui .rotate-270{transform:rotate(270deg)}.swagger-ui .rotate-315{transform:rotate(315deg)}@media screen and (min-width:30em){.swagger-ui .rotate-45-ns{transform:rotate(45deg)}.swagger-ui .rotate-90-ns{transform:rotate(90deg)}.swagger-ui .rotate-135-ns{transform:rotate(135deg)}.swagger-ui .rotate-180-ns{transform:rotate(180deg)}.swagger-ui .rotate-225-ns{transform:rotate(225deg)}.swagger-ui .rotate-270-ns{transform:rotate(270deg)}.swagger-ui .rotate-315-ns{transform:rotate(315deg)}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .rotate-45-m{transform:rotate(45deg)}.swagger-ui .rotate-90-m{transform:rotate(90deg)}.swagger-ui .rotate-135-m{transform:rotate(135deg)}.swagger-ui .rotate-180-m{transform:rotate(180deg)}.swagger-ui .rotate-225-m{transform:rotate(225deg)}.swagger-ui .rotate-270-m{transform:rotate(270deg)}.swagger-ui .rotate-315-m{transform:rotate(315deg)}}@media screen and (min-width:60em){.swagger-ui .rotate-45-l{transform:rotate(45deg)}.swagger-ui .rotate-90-l{transform:rotate(90deg)}.swagger-ui .rotate-135-l{transform:rotate(135deg)}.swagger-ui .rotate-180-l{transform:rotate(180deg)}.swagger-ui .rotate-225-l{transform:rotate(225deg)}.swagger-ui .rotate-270-l{transform:rotate(270deg)}.swagger-ui .rotate-315-l{transform:rotate(315deg)}}.swagger-ui .black-90{color:rgba(0,0,0,.9)}.swagger-ui .black-80{color:rgba(0,0,0,.8)}.swagger-ui .black-70{color:rgba(0,0,0,.7)}.swagger-ui .black-60{color:rgba(0,0,0,.6)}.swagger-ui .black-50{color:rgba(0,0,0,.5)}.swagger-ui .black-40{color:rgba(0,0,0,.4)}.swagger-ui .black-30{color:rgba(0,0,0,.3)}.swagger-ui .black-20{color:rgba(0,0,0,.2)}.swagger-ui .black-10{color:rgba(0,0,0,.1)}.swagger-ui .black-05{color:rgba(0,0,0,.05)}.swagger-ui .white-90{color:hsla(0,0%,100%,.9)}.swagger-ui .white-80{color:hsla(0,0%,100%,.8)}.swagger-ui .white-70{color:hsla(0,0%,100%,.7)}.swagger-ui .white-60{color:hsla(0,0%,100%,.6)}.swagger-ui .white-50{color:hsla(0,0%,100%,.5)}.swagger-ui .white-40{color:hsla(0,0%,100%,.4)}.swagger-ui .white-30{color:hsla(0,0%,100%,.3)}.swagger-ui .white-20{color:hsla(0,0%,100%,.2)}.swagger-ui .white-10{color:hsla(0,0%,100%,.1)}.swagger-ui .black{color:#000}.swagger-ui .near-black{color:#111}.swagger-ui .dark-gray{color:#333}.swagger-ui .mid-gray{color:#555}.swagger-ui .gray{color:#777}.swagger-ui .silver{color:#999}.swagger-ui .light-silver{color:#aaa}.swagger-ui .moon-gray{color:#ccc}.swagger-ui .light-gray{color:#eee}.swagger-ui .near-white{color:#f4f4f4}.swagger-ui .white{color:#fff}.swagger-ui .dark-red{color:#e7040f}.swagger-ui .red{color:#ff4136}.swagger-ui .light-red{color:#ff725c}.swagger-ui .orange{color:#ff6300}.swagger-ui .gold{color:#ffb700}.swagger-ui .yellow{color:gold}.swagger-ui .light-yellow{color:#fbf1a9}.swagger-ui .purple{color:#5e2ca5}.swagger-ui .light-purple{color:#a463f2}.swagger-ui .dark-pink{color:#d5008f}.swagger-ui .hot-pink{color:#ff41b4}.swagger-ui .pink{color:#ff80cc}.swagger-ui .light-pink{color:#ffa3d7}.swagger-ui .dark-green{color:#137752}.swagger-ui .green{color:#19a974}.swagger-ui .light-green{color:#9eebcf}.swagger-ui .navy{color:#001b44}.swagger-ui .dark-blue{color:#00449e}.swagger-ui .blue{color:#357edd}.swagger-ui .light-blue{color:#96ccff}.swagger-ui .lightest-blue{color:#cdecff}.swagger-ui .washed-blue{color:#f6fffe}.swagger-ui .washed-green{color:#e8fdf5}.swagger-ui .washed-yellow{color:#fffceb}.swagger-ui .washed-red{color:#ffdfdf}.swagger-ui .color-inherit{color:inherit}.swagger-ui .bg-black-90{background-color:rgba(0,0,0,.9)}.swagger-ui .bg-black-80{background-color:rgba(0,0,0,.8)}.swagger-ui .bg-black-70{background-color:rgba(0,0,0,.7)}.swagger-ui .bg-black-60{background-color:rgba(0,0,0,.6)}.swagger-ui .bg-black-50{background-color:rgba(0,0,0,.5)}.swagger-ui .bg-black-40{background-color:rgba(0,0,0,.4)}.swagger-ui .bg-black-30{background-color:rgba(0,0,0,.3)}.swagger-ui .bg-black-20{background-color:rgba(0,0,0,.2)}.swagger-ui .bg-black-10{background-color:rgba(0,0,0,.1)}.swagger-ui .bg-black-05{background-color:rgba(0,0,0,.05)}.swagger-ui .bg-white-90{background-color:hsla(0,0%,100%,.9)}.swagger-ui .bg-white-80{background-color:hsla(0,0%,100%,.8)}.swagger-ui .bg-white-70{background-color:hsla(0,0%,100%,.7)}.swagger-ui .bg-white-60{background-color:hsla(0,0%,100%,.6)}.swagger-ui .bg-white-50{background-color:hsla(0,0%,100%,.5)}.swagger-ui .bg-white-40{background-color:hsla(0,0%,100%,.4)}.swagger-ui .bg-white-30{background-color:hsla(0,0%,100%,.3)}.swagger-ui .bg-white-20{background-color:hsla(0,0%,100%,.2)}.swagger-ui .bg-white-10{background-color:hsla(0,0%,100%,.1)}.swagger-ui .bg-black{background-color:#000}.swagger-ui .bg-near-black{background-color:#111}.swagger-ui .bg-dark-gray{background-color:#333}.swagger-ui .bg-mid-gray{background-color:#555}.swagger-ui .bg-gray{background-color:#777}.swagger-ui .bg-silver{background-color:#999}.swagger-ui .bg-light-silver{background-color:#aaa}.swagger-ui .bg-moon-gray{background-color:#ccc}.swagger-ui .bg-light-gray{background-color:#eee}.swagger-ui .bg-near-white{background-color:#f4f4f4}.swagger-ui .bg-white{background-color:#fff}.swagger-ui .bg-transparent{background-color:transparent}.swagger-ui .bg-dark-red{background-color:#e7040f}.swagger-ui .bg-red{background-color:#ff4136}.swagger-ui .bg-light-red{background-color:#ff725c}.swagger-ui .bg-orange{background-color:#ff6300}.swagger-ui .bg-gold{background-color:#ffb700}.swagger-ui .bg-yellow{background-color:gold}.swagger-ui .bg-light-yellow{background-color:#fbf1a9}.swagger-ui .bg-purple{background-color:#5e2ca5}.swagger-ui .bg-light-purple{background-color:#a463f2}.swagger-ui .bg-dark-pink{background-color:#d5008f}.swagger-ui .bg-hot-pink{background-color:#ff41b4}.swagger-ui .bg-pink{background-color:#ff80cc}.swagger-ui .bg-light-pink{background-color:#ffa3d7}.swagger-ui .bg-dark-green{background-color:#137752}.swagger-ui .bg-green{background-color:#19a974}.swagger-ui .bg-light-green{background-color:#9eebcf}.swagger-ui .bg-navy{background-color:#001b44}.swagger-ui .bg-dark-blue{background-color:#00449e}.swagger-ui .bg-blue{background-color:#357edd}.swagger-ui .bg-light-blue{background-color:#96ccff}.swagger-ui .bg-lightest-blue{background-color:#cdecff}.swagger-ui .bg-washed-blue{background-color:#f6fffe}.swagger-ui .bg-washed-green{background-color:#e8fdf5}.swagger-ui .bg-washed-yellow{background-color:#fffceb}.swagger-ui .bg-washed-red{background-color:#ffdfdf}.swagger-ui .bg-inherit{background-color:inherit}.swagger-ui .hover-black:focus,.swagger-ui .hover-black:hover{color:#000}.swagger-ui .hover-near-black:focus,.swagger-ui .hover-near-black:hover{color:#111}.swagger-ui .hover-dark-gray:focus,.swagger-ui .hover-dark-gray:hover{color:#333}.swagger-ui .hover-mid-gray:focus,.swagger-ui .hover-mid-gray:hover{color:#555}.swagger-ui .hover-gray:focus,.swagger-ui .hover-gray:hover{color:#777}.swagger-ui .hover-silver:focus,.swagger-ui .hover-silver:hover{color:#999}.swagger-ui .hover-light-silver:focus,.swagger-ui .hover-light-silver:hover{color:#aaa}.swagger-ui .hover-moon-gray:focus,.swagger-ui .hover-moon-gray:hover{color:#ccc}.swagger-ui .hover-light-gray:focus,.swagger-ui .hover-light-gray:hover{color:#eee}.swagger-ui .hover-near-white:focus,.swagger-ui .hover-near-white:hover{color:#f4f4f4}.swagger-ui .hover-white:focus,.swagger-ui .hover-white:hover{color:#fff}.swagger-ui .hover-black-90:focus,.swagger-ui .hover-black-90:hover{color:rgba(0,0,0,.9)}.swagger-ui .hover-black-80:focus,.swagger-ui .hover-black-80:hover{color:rgba(0,0,0,.8)}.swagger-ui .hover-black-70:focus,.swagger-ui .hover-black-70:hover{color:rgba(0,0,0,.7)}.swagger-ui .hover-black-60:focus,.swagger-ui .hover-black-60:hover{color:rgba(0,0,0,.6)}.swagger-ui .hover-black-50:focus,.swagger-ui .hover-black-50:hover{color:rgba(0,0,0,.5)}.swagger-ui .hover-black-40:focus,.swagger-ui .hover-black-40:hover{color:rgba(0,0,0,.4)}.swagger-ui .hover-black-30:focus,.swagger-ui .hover-black-30:hover{color:rgba(0,0,0,.3)}.swagger-ui .hover-black-20:focus,.swagger-ui .hover-black-20:hover{color:rgba(0,0,0,.2)}.swagger-ui .hover-black-10:focus,.swagger-ui .hover-black-10:hover{color:rgba(0,0,0,.1)}.swagger-ui .hover-white-90:focus,.swagger-ui .hover-white-90:hover{color:hsla(0,0%,100%,.9)}.swagger-ui .hover-white-80:focus,.swagger-ui .hover-white-80:hover{color:hsla(0,0%,100%,.8)}.swagger-ui .hover-white-70:focus,.swagger-ui .hover-white-70:hover{color:hsla(0,0%,100%,.7)}.swagger-ui .hover-white-60:focus,.swagger-ui .hover-white-60:hover{color:hsla(0,0%,100%,.6)}.swagger-ui .hover-white-50:focus,.swagger-ui .hover-white-50:hover{color:hsla(0,0%,100%,.5)}.swagger-ui .hover-white-40:focus,.swagger-ui .hover-white-40:hover{color:hsla(0,0%,100%,.4)}.swagger-ui .hover-white-30:focus,.swagger-ui .hover-white-30:hover{color:hsla(0,0%,100%,.3)}.swagger-ui .hover-white-20:focus,.swagger-ui .hover-white-20:hover{color:hsla(0,0%,100%,.2)}.swagger-ui .hover-white-10:focus,.swagger-ui .hover-white-10:hover{color:hsla(0,0%,100%,.1)}.swagger-ui .hover-inherit:focus,.swagger-ui .hover-inherit:hover{color:inherit}.swagger-ui .hover-bg-black:focus,.swagger-ui .hover-bg-black:hover{background-color:#000}.swagger-ui .hover-bg-near-black:focus,.swagger-ui .hover-bg-near-black:hover{background-color:#111}.swagger-ui .hover-bg-dark-gray:focus,.swagger-ui .hover-bg-dark-gray:hover{background-color:#333}.swagger-ui .hover-bg-mid-gray:focus,.swagger-ui .hover-bg-mid-gray:hover{background-color:#555}.swagger-ui .hover-bg-gray:focus,.swagger-ui .hover-bg-gray:hover{background-color:#777}.swagger-ui .hover-bg-silver:focus,.swagger-ui .hover-bg-silver:hover{background-color:#999}.swagger-ui .hover-bg-light-silver:focus,.swagger-ui .hover-bg-light-silver:hover{background-color:#aaa}.swagger-ui .hover-bg-moon-gray:focus,.swagger-ui .hover-bg-moon-gray:hover{background-color:#ccc}.swagger-ui .hover-bg-light-gray:focus,.swagger-ui .hover-bg-light-gray:hover{background-color:#eee}.swagger-ui .hover-bg-near-white:focus,.swagger-ui .hover-bg-near-white:hover{background-color:#f4f4f4}.swagger-ui .hover-bg-white:focus,.swagger-ui .hover-bg-white:hover{background-color:#fff}.swagger-ui .hover-bg-transparent:focus,.swagger-ui .hover-bg-transparent:hover{background-color:transparent}.swagger-ui .hover-bg-black-90:focus,.swagger-ui .hover-bg-black-90:hover{background-color:rgba(0,0,0,.9)}.swagger-ui .hover-bg-black-80:focus,.swagger-ui .hover-bg-black-80:hover{background-color:rgba(0,0,0,.8)}.swagger-ui .hover-bg-black-70:focus,.swagger-ui .hover-bg-black-70:hover{background-color:rgba(0,0,0,.7)}.swagger-ui .hover-bg-black-60:focus,.swagger-ui .hover-bg-black-60:hover{background-color:rgba(0,0,0,.6)}.swagger-ui .hover-bg-black-50:focus,.swagger-ui .hover-bg-black-50:hover{background-color:rgba(0,0,0,.5)}.swagger-ui .hover-bg-black-40:focus,.swagger-ui .hover-bg-black-40:hover{background-color:rgba(0,0,0,.4)}.swagger-ui .hover-bg-black-30:focus,.swagger-ui .hover-bg-black-30:hover{background-color:rgba(0,0,0,.3)}.swagger-ui .hover-bg-black-20:focus,.swagger-ui .hover-bg-black-20:hover{background-color:rgba(0,0,0,.2)}.swagger-ui .hover-bg-black-10:focus,.swagger-ui .hover-bg-black-10:hover{background-color:rgba(0,0,0,.1)}.swagger-ui .hover-bg-white-90:focus,.swagger-ui .hover-bg-white-90:hover{background-color:hsla(0,0%,100%,.9)}.swagger-ui .hover-bg-white-80:focus,.swagger-ui .hover-bg-white-80:hover{background-color:hsla(0,0%,100%,.8)}.swagger-ui .hover-bg-white-70:focus,.swagger-ui .hover-bg-white-70:hover{background-color:hsla(0,0%,100%,.7)}.swagger-ui .hover-bg-white-60:focus,.swagger-ui .hover-bg-white-60:hover{background-color:hsla(0,0%,100%,.6)}.swagger-ui .hover-bg-white-50:focus,.swagger-ui .hover-bg-white-50:hover{background-color:hsla(0,0%,100%,.5)}.swagger-ui .hover-bg-white-40:focus,.swagger-ui .hover-bg-white-40:hover{background-color:hsla(0,0%,100%,.4)}.swagger-ui .hover-bg-white-30:focus,.swagger-ui .hover-bg-white-30:hover{background-color:hsla(0,0%,100%,.3)}.swagger-ui .hover-bg-white-20:focus,.swagger-ui .hover-bg-white-20:hover{background-color:hsla(0,0%,100%,.2)}.swagger-ui .hover-bg-white-10:focus,.swagger-ui .hover-bg-white-10:hover{background-color:hsla(0,0%,100%,.1)}.swagger-ui .hover-dark-red:focus,.swagger-ui .hover-dark-red:hover{color:#e7040f}.swagger-ui .hover-red:focus,.swagger-ui .hover-red:hover{color:#ff4136}.swagger-ui .hover-light-red:focus,.swagger-ui .hover-light-red:hover{color:#ff725c}.swagger-ui .hover-orange:focus,.swagger-ui .hover-orange:hover{color:#ff6300}.swagger-ui .hover-gold:focus,.swagger-ui .hover-gold:hover{color:#ffb700}.swagger-ui .hover-yellow:focus,.swagger-ui .hover-yellow:hover{color:gold}.swagger-ui .hover-light-yellow:focus,.swagger-ui .hover-light-yellow:hover{color:#fbf1a9}.swagger-ui .hover-purple:focus,.swagger-ui .hover-purple:hover{color:#5e2ca5}.swagger-ui .hover-light-purple:focus,.swagger-ui .hover-light-purple:hover{color:#a463f2}.swagger-ui .hover-dark-pink:focus,.swagger-ui .hover-dark-pink:hover{color:#d5008f}.swagger-ui .hover-hot-pink:focus,.swagger-ui .hover-hot-pink:hover{color:#ff41b4}.swagger-ui .hover-pink:focus,.swagger-ui .hover-pink:hover{color:#ff80cc}.swagger-ui .hover-light-pink:focus,.swagger-ui .hover-light-pink:hover{color:#ffa3d7}.swagger-ui .hover-dark-green:focus,.swagger-ui .hover-dark-green:hover{color:#137752}.swagger-ui .hover-green:focus,.swagger-ui .hover-green:hover{color:#19a974}.swagger-ui .hover-light-green:focus,.swagger-ui .hover-light-green:hover{color:#9eebcf}.swagger-ui .hover-navy:focus,.swagger-ui .hover-navy:hover{color:#001b44}.swagger-ui .hover-dark-blue:focus,.swagger-ui .hover-dark-blue:hover{color:#00449e}.swagger-ui .hover-blue:focus,.swagger-ui .hover-blue:hover{color:#357edd}.swagger-ui .hover-light-blue:focus,.swagger-ui .hover-light-blue:hover{color:#96ccff}.swagger-ui .hover-lightest-blue:focus,.swagger-ui .hover-lightest-blue:hover{color:#cdecff}.swagger-ui .hover-washed-blue:focus,.swagger-ui .hover-washed-blue:hover{color:#f6fffe}.swagger-ui .hover-washed-green:focus,.swagger-ui .hover-washed-green:hover{color:#e8fdf5}.swagger-ui .hover-washed-yellow:focus,.swagger-ui .hover-washed-yellow:hover{color:#fffceb}.swagger-ui .hover-washed-red:focus,.swagger-ui .hover-washed-red:hover{color:#ffdfdf}.swagger-ui .hover-bg-dark-red:focus,.swagger-ui .hover-bg-dark-red:hover{background-color:#e7040f}.swagger-ui .hover-bg-red:focus,.swagger-ui .hover-bg-red:hover{background-color:#ff4136}.swagger-ui .hover-bg-light-red:focus,.swagger-ui .hover-bg-light-red:hover{background-color:#ff725c}.swagger-ui .hover-bg-orange:focus,.swagger-ui .hover-bg-orange:hover{background-color:#ff6300}.swagger-ui .hover-bg-gold:focus,.swagger-ui .hover-bg-gold:hover{background-color:#ffb700}.swagger-ui .hover-bg-yellow:focus,.swagger-ui .hover-bg-yellow:hover{background-color:gold}.swagger-ui .hover-bg-light-yellow:focus,.swagger-ui .hover-bg-light-yellow:hover{background-color:#fbf1a9}.swagger-ui .hover-bg-purple:focus,.swagger-ui .hover-bg-purple:hover{background-color:#5e2ca5}.swagger-ui .hover-bg-light-purple:focus,.swagger-ui .hover-bg-light-purple:hover{background-color:#a463f2}.swagger-ui .hover-bg-dark-pink:focus,.swagger-ui .hover-bg-dark-pink:hover{background-color:#d5008f}.swagger-ui .hover-bg-hot-pink:focus,.swagger-ui .hover-bg-hot-pink:hover{background-color:#ff41b4}.swagger-ui .hover-bg-pink:focus,.swagger-ui .hover-bg-pink:hover{background-color:#ff80cc}.swagger-ui .hover-bg-light-pink:focus,.swagger-ui .hover-bg-light-pink:hover{background-color:#ffa3d7}.swagger-ui .hover-bg-dark-green:focus,.swagger-ui .hover-bg-dark-green:hover{background-color:#137752}.swagger-ui .hover-bg-green:focus,.swagger-ui .hover-bg-green:hover{background-color:#19a974}.swagger-ui .hover-bg-light-green:focus,.swagger-ui .hover-bg-light-green:hover{background-color:#9eebcf}.swagger-ui .hover-bg-navy:focus,.swagger-ui .hover-bg-navy:hover{background-color:#001b44}.swagger-ui .hover-bg-dark-blue:focus,.swagger-ui .hover-bg-dark-blue:hover{background-color:#00449e}.swagger-ui .hover-bg-blue:focus,.swagger-ui .hover-bg-blue:hover{background-color:#357edd}.swagger-ui .hover-bg-light-blue:focus,.swagger-ui .hover-bg-light-blue:hover{background-color:#96ccff}.swagger-ui .hover-bg-lightest-blue:focus,.swagger-ui .hover-bg-lightest-blue:hover{background-color:#cdecff}.swagger-ui .hover-bg-washed-blue:focus,.swagger-ui .hover-bg-washed-blue:hover{background-color:#f6fffe}.swagger-ui .hover-bg-washed-green:focus,.swagger-ui .hover-bg-washed-green:hover{background-color:#e8fdf5}.swagger-ui .hover-bg-washed-yellow:focus,.swagger-ui .hover-bg-washed-yellow:hover{background-color:#fffceb}.swagger-ui .hover-bg-washed-red:focus,.swagger-ui .hover-bg-washed-red:hover{background-color:#ffdfdf}.swagger-ui .hover-bg-inherit:focus,.swagger-ui .hover-bg-inherit:hover{background-color:inherit}.swagger-ui .pa0{padding:0}.swagger-ui .pa1{padding:.25rem}.swagger-ui .pa2{padding:.5rem}.swagger-ui .pa3{padding:1rem}.swagger-ui .pa4{padding:2rem}.swagger-ui .pa5{padding:4rem}.swagger-ui .pa6{padding:8rem}.swagger-ui .pa7{padding:16rem}.swagger-ui .pl0{padding-left:0}.swagger-ui .pl1{padding-left:.25rem}.swagger-ui .pl2{padding-left:.5rem}.swagger-ui .pl3{padding-left:1rem}.swagger-ui .pl4{padding-left:2rem}.swagger-ui .pl5{padding-left:4rem}.swagger-ui .pl6{padding-left:8rem}.swagger-ui .pl7{padding-left:16rem}.swagger-ui .pr0{padding-right:0}.swagger-ui .pr1{padding-right:.25rem}.swagger-ui .pr2{padding-right:.5rem}.swagger-ui .pr3{padding-right:1rem}.swagger-ui .pr4{padding-right:2rem}.swagger-ui .pr5{padding-right:4rem}.swagger-ui .pr6{padding-right:8rem}.swagger-ui .pr7{padding-right:16rem}.swagger-ui .pb0{padding-bottom:0}.swagger-ui .pb1{padding-bottom:.25rem}.swagger-ui .pb2{padding-bottom:.5rem}.swagger-ui .pb3{padding-bottom:1rem}.swagger-ui .pb4{padding-bottom:2rem}.swagger-ui .pb5{padding-bottom:4rem}.swagger-ui .pb6{padding-bottom:8rem}.swagger-ui .pb7{padding-bottom:16rem}.swagger-ui .pt0{padding-top:0}.swagger-ui .pt1{padding-top:.25rem}.swagger-ui .pt2{padding-top:.5rem}.swagger-ui .pt3{padding-top:1rem}.swagger-ui .pt4{padding-top:2rem}.swagger-ui .pt5{padding-top:4rem}.swagger-ui .pt6{padding-top:8rem}.swagger-ui .pt7{padding-top:16rem}.swagger-ui .pv0{padding-bottom:0;padding-top:0}.swagger-ui .pv1{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0{padding-left:0;padding-right:0}.swagger-ui .ph1{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0{margin:0}.swagger-ui .ma1{margin:.25rem}.swagger-ui .ma2{margin:.5rem}.swagger-ui .ma3{margin:1rem}.swagger-ui .ma4{margin:2rem}.swagger-ui .ma5{margin:4rem}.swagger-ui .ma6{margin:8rem}.swagger-ui .ma7{margin:16rem}.swagger-ui .ml0{margin-left:0}.swagger-ui .ml1{margin-left:.25rem}.swagger-ui .ml2{margin-left:.5rem}.swagger-ui .ml3{margin-left:1rem}.swagger-ui .ml4{margin-left:2rem}.swagger-ui .ml5{margin-left:4rem}.swagger-ui .ml6{margin-left:8rem}.swagger-ui .ml7{margin-left:16rem}.swagger-ui .mr0{margin-right:0}.swagger-ui .mr1{margin-right:.25rem}.swagger-ui .mr2{margin-right:.5rem}.swagger-ui .mr3{margin-right:1rem}.swagger-ui .mr4{margin-right:2rem}.swagger-ui .mr5{margin-right:4rem}.swagger-ui .mr6{margin-right:8rem}.swagger-ui .mr7{margin-right:16rem}.swagger-ui .mb0{margin-bottom:0}.swagger-ui .mb1{margin-bottom:.25rem}.swagger-ui .mb2{margin-bottom:.5rem}.swagger-ui .mb3{margin-bottom:1rem}.swagger-ui .mb4{margin-bottom:2rem}.swagger-ui .mb5{margin-bottom:4rem}.swagger-ui .mb6{margin-bottom:8rem}.swagger-ui .mb7{margin-bottom:16rem}.swagger-ui .mt0{margin-top:0}.swagger-ui .mt1{margin-top:.25rem}.swagger-ui .mt2{margin-top:.5rem}.swagger-ui .mt3{margin-top:1rem}.swagger-ui .mt4{margin-top:2rem}.swagger-ui .mt5{margin-top:4rem}.swagger-ui .mt6{margin-top:8rem}.swagger-ui .mt7{margin-top:16rem}.swagger-ui .mv0{margin-bottom:0;margin-top:0}.swagger-ui .mv1{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0{margin-left:0;margin-right:0}.swagger-ui .mh1{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7{margin-left:16rem;margin-right:16rem}@media screen and (min-width:30em){.swagger-ui .pa0-ns{padding:0}.swagger-ui .pa1-ns{padding:.25rem}.swagger-ui .pa2-ns{padding:.5rem}.swagger-ui .pa3-ns{padding:1rem}.swagger-ui .pa4-ns{padding:2rem}.swagger-ui .pa5-ns{padding:4rem}.swagger-ui .pa6-ns{padding:8rem}.swagger-ui .pa7-ns{padding:16rem}.swagger-ui .pl0-ns{padding-left:0}.swagger-ui .pl1-ns{padding-left:.25rem}.swagger-ui .pl2-ns{padding-left:.5rem}.swagger-ui .pl3-ns{padding-left:1rem}.swagger-ui .pl4-ns{padding-left:2rem}.swagger-ui .pl5-ns{padding-left:4rem}.swagger-ui .pl6-ns{padding-left:8rem}.swagger-ui .pl7-ns{padding-left:16rem}.swagger-ui .pr0-ns{padding-right:0}.swagger-ui .pr1-ns{padding-right:.25rem}.swagger-ui .pr2-ns{padding-right:.5rem}.swagger-ui .pr3-ns{padding-right:1rem}.swagger-ui .pr4-ns{padding-right:2rem}.swagger-ui .pr5-ns{padding-right:4rem}.swagger-ui .pr6-ns{padding-right:8rem}.swagger-ui .pr7-ns{padding-right:16rem}.swagger-ui .pb0-ns{padding-bottom:0}.swagger-ui .pb1-ns{padding-bottom:.25rem}.swagger-ui .pb2-ns{padding-bottom:.5rem}.swagger-ui .pb3-ns{padding-bottom:1rem}.swagger-ui .pb4-ns{padding-bottom:2rem}.swagger-ui .pb5-ns{padding-bottom:4rem}.swagger-ui .pb6-ns{padding-bottom:8rem}.swagger-ui .pb7-ns{padding-bottom:16rem}.swagger-ui .pt0-ns{padding-top:0}.swagger-ui .pt1-ns{padding-top:.25rem}.swagger-ui .pt2-ns{padding-top:.5rem}.swagger-ui .pt3-ns{padding-top:1rem}.swagger-ui .pt4-ns{padding-top:2rem}.swagger-ui .pt5-ns{padding-top:4rem}.swagger-ui .pt6-ns{padding-top:8rem}.swagger-ui .pt7-ns{padding-top:16rem}.swagger-ui .pv0-ns{padding-bottom:0;padding-top:0}.swagger-ui .pv1-ns{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-ns{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-ns{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-ns{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-ns{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-ns{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-ns{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-ns{padding-left:0;padding-right:0}.swagger-ui .ph1-ns{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-ns{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-ns{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-ns{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-ns{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-ns{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-ns{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-ns{margin:0}.swagger-ui .ma1-ns{margin:.25rem}.swagger-ui .ma2-ns{margin:.5rem}.swagger-ui .ma3-ns{margin:1rem}.swagger-ui .ma4-ns{margin:2rem}.swagger-ui .ma5-ns{margin:4rem}.swagger-ui .ma6-ns{margin:8rem}.swagger-ui .ma7-ns{margin:16rem}.swagger-ui .ml0-ns{margin-left:0}.swagger-ui .ml1-ns{margin-left:.25rem}.swagger-ui .ml2-ns{margin-left:.5rem}.swagger-ui .ml3-ns{margin-left:1rem}.swagger-ui .ml4-ns{margin-left:2rem}.swagger-ui .ml5-ns{margin-left:4rem}.swagger-ui .ml6-ns{margin-left:8rem}.swagger-ui .ml7-ns{margin-left:16rem}.swagger-ui .mr0-ns{margin-right:0}.swagger-ui .mr1-ns{margin-right:.25rem}.swagger-ui .mr2-ns{margin-right:.5rem}.swagger-ui .mr3-ns{margin-right:1rem}.swagger-ui .mr4-ns{margin-right:2rem}.swagger-ui .mr5-ns{margin-right:4rem}.swagger-ui .mr6-ns{margin-right:8rem}.swagger-ui .mr7-ns{margin-right:16rem}.swagger-ui .mb0-ns{margin-bottom:0}.swagger-ui .mb1-ns{margin-bottom:.25rem}.swagger-ui .mb2-ns{margin-bottom:.5rem}.swagger-ui .mb3-ns{margin-bottom:1rem}.swagger-ui .mb4-ns{margin-bottom:2rem}.swagger-ui .mb5-ns{margin-bottom:4rem}.swagger-ui .mb6-ns{margin-bottom:8rem}.swagger-ui .mb7-ns{margin-bottom:16rem}.swagger-ui .mt0-ns{margin-top:0}.swagger-ui .mt1-ns{margin-top:.25rem}.swagger-ui .mt2-ns{margin-top:.5rem}.swagger-ui .mt3-ns{margin-top:1rem}.swagger-ui .mt4-ns{margin-top:2rem}.swagger-ui .mt5-ns{margin-top:4rem}.swagger-ui .mt6-ns{margin-top:8rem}.swagger-ui .mt7-ns{margin-top:16rem}.swagger-ui .mv0-ns{margin-bottom:0;margin-top:0}.swagger-ui .mv1-ns{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-ns{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-ns{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-ns{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-ns{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-ns{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-ns{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-ns{margin-left:0;margin-right:0}.swagger-ui .mh1-ns{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-ns{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-ns{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-ns{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-ns{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-ns{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-ns{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .pa0-m{padding:0}.swagger-ui .pa1-m{padding:.25rem}.swagger-ui .pa2-m{padding:.5rem}.swagger-ui .pa3-m{padding:1rem}.swagger-ui .pa4-m{padding:2rem}.swagger-ui .pa5-m{padding:4rem}.swagger-ui .pa6-m{padding:8rem}.swagger-ui .pa7-m{padding:16rem}.swagger-ui .pl0-m{padding-left:0}.swagger-ui .pl1-m{padding-left:.25rem}.swagger-ui .pl2-m{padding-left:.5rem}.swagger-ui .pl3-m{padding-left:1rem}.swagger-ui .pl4-m{padding-left:2rem}.swagger-ui .pl5-m{padding-left:4rem}.swagger-ui .pl6-m{padding-left:8rem}.swagger-ui .pl7-m{padding-left:16rem}.swagger-ui .pr0-m{padding-right:0}.swagger-ui .pr1-m{padding-right:.25rem}.swagger-ui .pr2-m{padding-right:.5rem}.swagger-ui .pr3-m{padding-right:1rem}.swagger-ui .pr4-m{padding-right:2rem}.swagger-ui .pr5-m{padding-right:4rem}.swagger-ui .pr6-m{padding-right:8rem}.swagger-ui .pr7-m{padding-right:16rem}.swagger-ui .pb0-m{padding-bottom:0}.swagger-ui .pb1-m{padding-bottom:.25rem}.swagger-ui .pb2-m{padding-bottom:.5rem}.swagger-ui .pb3-m{padding-bottom:1rem}.swagger-ui .pb4-m{padding-bottom:2rem}.swagger-ui .pb5-m{padding-bottom:4rem}.swagger-ui .pb6-m{padding-bottom:8rem}.swagger-ui .pb7-m{padding-bottom:16rem}.swagger-ui .pt0-m{padding-top:0}.swagger-ui .pt1-m{padding-top:.25rem}.swagger-ui .pt2-m{padding-top:.5rem}.swagger-ui .pt3-m{padding-top:1rem}.swagger-ui .pt4-m{padding-top:2rem}.swagger-ui .pt5-m{padding-top:4rem}.swagger-ui .pt6-m{padding-top:8rem}.swagger-ui .pt7-m{padding-top:16rem}.swagger-ui .pv0-m{padding-bottom:0;padding-top:0}.swagger-ui .pv1-m{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-m{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-m{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-m{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-m{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-m{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-m{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-m{padding-left:0;padding-right:0}.swagger-ui .ph1-m{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-m{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-m{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-m{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-m{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-m{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-m{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-m{margin:0}.swagger-ui .ma1-m{margin:.25rem}.swagger-ui .ma2-m{margin:.5rem}.swagger-ui .ma3-m{margin:1rem}.swagger-ui .ma4-m{margin:2rem}.swagger-ui .ma5-m{margin:4rem}.swagger-ui .ma6-m{margin:8rem}.swagger-ui .ma7-m{margin:16rem}.swagger-ui .ml0-m{margin-left:0}.swagger-ui .ml1-m{margin-left:.25rem}.swagger-ui .ml2-m{margin-left:.5rem}.swagger-ui .ml3-m{margin-left:1rem}.swagger-ui .ml4-m{margin-left:2rem}.swagger-ui .ml5-m{margin-left:4rem}.swagger-ui .ml6-m{margin-left:8rem}.swagger-ui .ml7-m{margin-left:16rem}.swagger-ui .mr0-m{margin-right:0}.swagger-ui .mr1-m{margin-right:.25rem}.swagger-ui .mr2-m{margin-right:.5rem}.swagger-ui .mr3-m{margin-right:1rem}.swagger-ui .mr4-m{margin-right:2rem}.swagger-ui .mr5-m{margin-right:4rem}.swagger-ui .mr6-m{margin-right:8rem}.swagger-ui .mr7-m{margin-right:16rem}.swagger-ui .mb0-m{margin-bottom:0}.swagger-ui .mb1-m{margin-bottom:.25rem}.swagger-ui .mb2-m{margin-bottom:.5rem}.swagger-ui .mb3-m{margin-bottom:1rem}.swagger-ui .mb4-m{margin-bottom:2rem}.swagger-ui .mb5-m{margin-bottom:4rem}.swagger-ui .mb6-m{margin-bottom:8rem}.swagger-ui .mb7-m{margin-bottom:16rem}.swagger-ui .mt0-m{margin-top:0}.swagger-ui .mt1-m{margin-top:.25rem}.swagger-ui .mt2-m{margin-top:.5rem}.swagger-ui .mt3-m{margin-top:1rem}.swagger-ui .mt4-m{margin-top:2rem}.swagger-ui .mt5-m{margin-top:4rem}.swagger-ui .mt6-m{margin-top:8rem}.swagger-ui .mt7-m{margin-top:16rem}.swagger-ui .mv0-m{margin-bottom:0;margin-top:0}.swagger-ui .mv1-m{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-m{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-m{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-m{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-m{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-m{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-m{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-m{margin-left:0;margin-right:0}.swagger-ui .mh1-m{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-m{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-m{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-m{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-m{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-m{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-m{margin-left:16rem;margin-right:16rem}}@media screen and (min-width:60em){.swagger-ui .pa0-l{padding:0}.swagger-ui .pa1-l{padding:.25rem}.swagger-ui .pa2-l{padding:.5rem}.swagger-ui .pa3-l{padding:1rem}.swagger-ui .pa4-l{padding:2rem}.swagger-ui .pa5-l{padding:4rem}.swagger-ui .pa6-l{padding:8rem}.swagger-ui .pa7-l{padding:16rem}.swagger-ui .pl0-l{padding-left:0}.swagger-ui .pl1-l{padding-left:.25rem}.swagger-ui .pl2-l{padding-left:.5rem}.swagger-ui .pl3-l{padding-left:1rem}.swagger-ui .pl4-l{padding-left:2rem}.swagger-ui .pl5-l{padding-left:4rem}.swagger-ui .pl6-l{padding-left:8rem}.swagger-ui .pl7-l{padding-left:16rem}.swagger-ui .pr0-l{padding-right:0}.swagger-ui .pr1-l{padding-right:.25rem}.swagger-ui .pr2-l{padding-right:.5rem}.swagger-ui .pr3-l{padding-right:1rem}.swagger-ui .pr4-l{padding-right:2rem}.swagger-ui .pr5-l{padding-right:4rem}.swagger-ui .pr6-l{padding-right:8rem}.swagger-ui .pr7-l{padding-right:16rem}.swagger-ui .pb0-l{padding-bottom:0}.swagger-ui .pb1-l{padding-bottom:.25rem}.swagger-ui .pb2-l{padding-bottom:.5rem}.swagger-ui .pb3-l{padding-bottom:1rem}.swagger-ui .pb4-l{padding-bottom:2rem}.swagger-ui .pb5-l{padding-bottom:4rem}.swagger-ui .pb6-l{padding-bottom:8rem}.swagger-ui .pb7-l{padding-bottom:16rem}.swagger-ui .pt0-l{padding-top:0}.swagger-ui .pt1-l{padding-top:.25rem}.swagger-ui .pt2-l{padding-top:.5rem}.swagger-ui .pt3-l{padding-top:1rem}.swagger-ui .pt4-l{padding-top:2rem}.swagger-ui .pt5-l{padding-top:4rem}.swagger-ui .pt6-l{padding-top:8rem}.swagger-ui .pt7-l{padding-top:16rem}.swagger-ui .pv0-l{padding-bottom:0;padding-top:0}.swagger-ui .pv1-l{padding-bottom:.25rem;padding-top:.25rem}.swagger-ui .pv2-l{padding-bottom:.5rem;padding-top:.5rem}.swagger-ui .pv3-l{padding-bottom:1rem;padding-top:1rem}.swagger-ui .pv4-l{padding-bottom:2rem;padding-top:2rem}.swagger-ui .pv5-l{padding-bottom:4rem;padding-top:4rem}.swagger-ui .pv6-l{padding-bottom:8rem;padding-top:8rem}.swagger-ui .pv7-l{padding-bottom:16rem;padding-top:16rem}.swagger-ui .ph0-l{padding-left:0;padding-right:0}.swagger-ui .ph1-l{padding-left:.25rem;padding-right:.25rem}.swagger-ui .ph2-l{padding-left:.5rem;padding-right:.5rem}.swagger-ui .ph3-l{padding-left:1rem;padding-right:1rem}.swagger-ui .ph4-l{padding-left:2rem;padding-right:2rem}.swagger-ui .ph5-l{padding-left:4rem;padding-right:4rem}.swagger-ui .ph6-l{padding-left:8rem;padding-right:8rem}.swagger-ui .ph7-l{padding-left:16rem;padding-right:16rem}.swagger-ui .ma0-l{margin:0}.swagger-ui .ma1-l{margin:.25rem}.swagger-ui .ma2-l{margin:.5rem}.swagger-ui .ma3-l{margin:1rem}.swagger-ui .ma4-l{margin:2rem}.swagger-ui .ma5-l{margin:4rem}.swagger-ui .ma6-l{margin:8rem}.swagger-ui .ma7-l{margin:16rem}.swagger-ui .ml0-l{margin-left:0}.swagger-ui .ml1-l{margin-left:.25rem}.swagger-ui .ml2-l{margin-left:.5rem}.swagger-ui .ml3-l{margin-left:1rem}.swagger-ui .ml4-l{margin-left:2rem}.swagger-ui .ml5-l{margin-left:4rem}.swagger-ui .ml6-l{margin-left:8rem}.swagger-ui .ml7-l{margin-left:16rem}.swagger-ui .mr0-l{margin-right:0}.swagger-ui .mr1-l{margin-right:.25rem}.swagger-ui .mr2-l{margin-right:.5rem}.swagger-ui .mr3-l{margin-right:1rem}.swagger-ui .mr4-l{margin-right:2rem}.swagger-ui .mr5-l{margin-right:4rem}.swagger-ui .mr6-l{margin-right:8rem}.swagger-ui .mr7-l{margin-right:16rem}.swagger-ui .mb0-l{margin-bottom:0}.swagger-ui .mb1-l{margin-bottom:.25rem}.swagger-ui .mb2-l{margin-bottom:.5rem}.swagger-ui .mb3-l{margin-bottom:1rem}.swagger-ui .mb4-l{margin-bottom:2rem}.swagger-ui .mb5-l{margin-bottom:4rem}.swagger-ui .mb6-l{margin-bottom:8rem}.swagger-ui .mb7-l{margin-bottom:16rem}.swagger-ui .mt0-l{margin-top:0}.swagger-ui .mt1-l{margin-top:.25rem}.swagger-ui .mt2-l{margin-top:.5rem}.swagger-ui .mt3-l{margin-top:1rem}.swagger-ui .mt4-l{margin-top:2rem}.swagger-ui .mt5-l{margin-top:4rem}.swagger-ui .mt6-l{margin-top:8rem}.swagger-ui .mt7-l{margin-top:16rem}.swagger-ui .mv0-l{margin-bottom:0;margin-top:0}.swagger-ui .mv1-l{margin-bottom:.25rem;margin-top:.25rem}.swagger-ui .mv2-l{margin-bottom:.5rem;margin-top:.5rem}.swagger-ui .mv3-l{margin-bottom:1rem;margin-top:1rem}.swagger-ui .mv4-l{margin-bottom:2rem;margin-top:2rem}.swagger-ui .mv5-l{margin-bottom:4rem;margin-top:4rem}.swagger-ui .mv6-l{margin-bottom:8rem;margin-top:8rem}.swagger-ui .mv7-l{margin-bottom:16rem;margin-top:16rem}.swagger-ui .mh0-l{margin-left:0;margin-right:0}.swagger-ui .mh1-l{margin-left:.25rem;margin-right:.25rem}.swagger-ui .mh2-l{margin-left:.5rem;margin-right:.5rem}.swagger-ui .mh3-l{margin-left:1rem;margin-right:1rem}.swagger-ui .mh4-l{margin-left:2rem;margin-right:2rem}.swagger-ui .mh5-l{margin-left:4rem;margin-right:4rem}.swagger-ui .mh6-l{margin-left:8rem;margin-right:8rem}.swagger-ui .mh7-l{margin-left:16rem;margin-right:16rem}}.swagger-ui .na1{margin:-.25rem}.swagger-ui .na2{margin:-.5rem}.swagger-ui .na3{margin:-1rem}.swagger-ui .na4{margin:-2rem}.swagger-ui .na5{margin:-4rem}.swagger-ui .na6{margin:-8rem}.swagger-ui .na7{margin:-16rem}.swagger-ui .nl1{margin-left:-.25rem}.swagger-ui .nl2{margin-left:-.5rem}.swagger-ui .nl3{margin-left:-1rem}.swagger-ui .nl4{margin-left:-2rem}.swagger-ui .nl5{margin-left:-4rem}.swagger-ui .nl6{margin-left:-8rem}.swagger-ui .nl7{margin-left:-16rem}.swagger-ui .nr1{margin-right:-.25rem}.swagger-ui .nr2{margin-right:-.5rem}.swagger-ui .nr3{margin-right:-1rem}.swagger-ui .nr4{margin-right:-2rem}.swagger-ui .nr5{margin-right:-4rem}.swagger-ui .nr6{margin-right:-8rem}.swagger-ui .nr7{margin-right:-16rem}.swagger-ui .nb1{margin-bottom:-.25rem}.swagger-ui .nb2{margin-bottom:-.5rem}.swagger-ui .nb3{margin-bottom:-1rem}.swagger-ui .nb4{margin-bottom:-2rem}.swagger-ui .nb5{margin-bottom:-4rem}.swagger-ui .nb6{margin-bottom:-8rem}.swagger-ui .nb7{margin-bottom:-16rem}.swagger-ui .nt1{margin-top:-.25rem}.swagger-ui .nt2{margin-top:-.5rem}.swagger-ui .nt3{margin-top:-1rem}.swagger-ui .nt4{margin-top:-2rem}.swagger-ui .nt5{margin-top:-4rem}.swagger-ui .nt6{margin-top:-8rem}.swagger-ui .nt7{margin-top:-16rem}@media screen and (min-width:30em){.swagger-ui .na1-ns{margin:-.25rem}.swagger-ui .na2-ns{margin:-.5rem}.swagger-ui .na3-ns{margin:-1rem}.swagger-ui .na4-ns{margin:-2rem}.swagger-ui .na5-ns{margin:-4rem}.swagger-ui .na6-ns{margin:-8rem}.swagger-ui .na7-ns{margin:-16rem}.swagger-ui .nl1-ns{margin-left:-.25rem}.swagger-ui .nl2-ns{margin-left:-.5rem}.swagger-ui .nl3-ns{margin-left:-1rem}.swagger-ui .nl4-ns{margin-left:-2rem}.swagger-ui .nl5-ns{margin-left:-4rem}.swagger-ui .nl6-ns{margin-left:-8rem}.swagger-ui .nl7-ns{margin-left:-16rem}.swagger-ui .nr1-ns{margin-right:-.25rem}.swagger-ui .nr2-ns{margin-right:-.5rem}.swagger-ui .nr3-ns{margin-right:-1rem}.swagger-ui .nr4-ns{margin-right:-2rem}.swagger-ui .nr5-ns{margin-right:-4rem}.swagger-ui .nr6-ns{margin-right:-8rem}.swagger-ui .nr7-ns{margin-right:-16rem}.swagger-ui .nb1-ns{margin-bottom:-.25rem}.swagger-ui .nb2-ns{margin-bottom:-.5rem}.swagger-ui .nb3-ns{margin-bottom:-1rem}.swagger-ui .nb4-ns{margin-bottom:-2rem}.swagger-ui .nb5-ns{margin-bottom:-4rem}.swagger-ui .nb6-ns{margin-bottom:-8rem}.swagger-ui .nb7-ns{margin-bottom:-16rem}.swagger-ui .nt1-ns{margin-top:-.25rem}.swagger-ui .nt2-ns{margin-top:-.5rem}.swagger-ui .nt3-ns{margin-top:-1rem}.swagger-ui .nt4-ns{margin-top:-2rem}.swagger-ui .nt5-ns{margin-top:-4rem}.swagger-ui .nt6-ns{margin-top:-8rem}.swagger-ui .nt7-ns{margin-top:-16rem}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .na1-m{margin:-.25rem}.swagger-ui .na2-m{margin:-.5rem}.swagger-ui .na3-m{margin:-1rem}.swagger-ui .na4-m{margin:-2rem}.swagger-ui .na5-m{margin:-4rem}.swagger-ui .na6-m{margin:-8rem}.swagger-ui .na7-m{margin:-16rem}.swagger-ui .nl1-m{margin-left:-.25rem}.swagger-ui .nl2-m{margin-left:-.5rem}.swagger-ui .nl3-m{margin-left:-1rem}.swagger-ui .nl4-m{margin-left:-2rem}.swagger-ui .nl5-m{margin-left:-4rem}.swagger-ui .nl6-m{margin-left:-8rem}.swagger-ui .nl7-m{margin-left:-16rem}.swagger-ui .nr1-m{margin-right:-.25rem}.swagger-ui .nr2-m{margin-right:-.5rem}.swagger-ui .nr3-m{margin-right:-1rem}.swagger-ui .nr4-m{margin-right:-2rem}.swagger-ui .nr5-m{margin-right:-4rem}.swagger-ui .nr6-m{margin-right:-8rem}.swagger-ui .nr7-m{margin-right:-16rem}.swagger-ui .nb1-m{margin-bottom:-.25rem}.swagger-ui .nb2-m{margin-bottom:-.5rem}.swagger-ui .nb3-m{margin-bottom:-1rem}.swagger-ui .nb4-m{margin-bottom:-2rem}.swagger-ui .nb5-m{margin-bottom:-4rem}.swagger-ui .nb6-m{margin-bottom:-8rem}.swagger-ui .nb7-m{margin-bottom:-16rem}.swagger-ui .nt1-m{margin-top:-.25rem}.swagger-ui .nt2-m{margin-top:-.5rem}.swagger-ui .nt3-m{margin-top:-1rem}.swagger-ui .nt4-m{margin-top:-2rem}.swagger-ui .nt5-m{margin-top:-4rem}.swagger-ui .nt6-m{margin-top:-8rem}.swagger-ui .nt7-m{margin-top:-16rem}}@media screen and (min-width:60em){.swagger-ui .na1-l{margin:-.25rem}.swagger-ui .na2-l{margin:-.5rem}.swagger-ui .na3-l{margin:-1rem}.swagger-ui .na4-l{margin:-2rem}.swagger-ui .na5-l{margin:-4rem}.swagger-ui .na6-l{margin:-8rem}.swagger-ui .na7-l{margin:-16rem}.swagger-ui .nl1-l{margin-left:-.25rem}.swagger-ui .nl2-l{margin-left:-.5rem}.swagger-ui .nl3-l{margin-left:-1rem}.swagger-ui .nl4-l{margin-left:-2rem}.swagger-ui .nl5-l{margin-left:-4rem}.swagger-ui .nl6-l{margin-left:-8rem}.swagger-ui .nl7-l{margin-left:-16rem}.swagger-ui .nr1-l{margin-right:-.25rem}.swagger-ui .nr2-l{margin-right:-.5rem}.swagger-ui .nr3-l{margin-right:-1rem}.swagger-ui .nr4-l{margin-right:-2rem}.swagger-ui .nr5-l{margin-right:-4rem}.swagger-ui .nr6-l{margin-right:-8rem}.swagger-ui .nr7-l{margin-right:-16rem}.swagger-ui .nb1-l{margin-bottom:-.25rem}.swagger-ui .nb2-l{margin-bottom:-.5rem}.swagger-ui .nb3-l{margin-bottom:-1rem}.swagger-ui .nb4-l{margin-bottom:-2rem}.swagger-ui .nb5-l{margin-bottom:-4rem}.swagger-ui .nb6-l{margin-bottom:-8rem}.swagger-ui .nb7-l{margin-bottom:-16rem}.swagger-ui .nt1-l{margin-top:-.25rem}.swagger-ui .nt2-l{margin-top:-.5rem}.swagger-ui .nt3-l{margin-top:-1rem}.swagger-ui .nt4-l{margin-top:-2rem}.swagger-ui .nt5-l{margin-top:-4rem}.swagger-ui .nt6-l{margin-top:-8rem}.swagger-ui .nt7-l{margin-top:-16rem}}.swagger-ui .collapse{border-collapse:collapse;border-spacing:0}.swagger-ui .striped--light-silver:nth-child(odd){background-color:#aaa}.swagger-ui .striped--moon-gray:nth-child(odd){background-color:#ccc}.swagger-ui .striped--light-gray:nth-child(odd){background-color:#eee}.swagger-ui .striped--near-white:nth-child(odd){background-color:#f4f4f4}.swagger-ui .stripe-light:nth-child(odd){background-color:hsla(0,0%,100%,.1)}.swagger-ui .stripe-dark:nth-child(odd){background-color:rgba(0,0,0,.1)}.swagger-ui .strike{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .underline{-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .no-underline{-webkit-text-decoration:none;text-decoration:none}@media screen and (min-width:30em){.swagger-ui .strike-ns{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .underline-ns{-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .no-underline-ns{-webkit-text-decoration:none;text-decoration:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .strike-m{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .underline-m{-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .no-underline-m{-webkit-text-decoration:none;text-decoration:none}}@media screen and (min-width:60em){.swagger-ui .strike-l{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .underline-l{-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .no-underline-l{-webkit-text-decoration:none;text-decoration:none}}.swagger-ui .tl{text-align:left}.swagger-ui .tr{text-align:right}.swagger-ui .tc{text-align:center}.swagger-ui .tj{text-align:justify}@media screen and (min-width:30em){.swagger-ui .tl-ns{text-align:left}.swagger-ui .tr-ns{text-align:right}.swagger-ui .tc-ns{text-align:center}.swagger-ui .tj-ns{text-align:justify}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .tl-m{text-align:left}.swagger-ui .tr-m{text-align:right}.swagger-ui .tc-m{text-align:center}.swagger-ui .tj-m{text-align:justify}}@media screen and (min-width:60em){.swagger-ui .tl-l{text-align:left}.swagger-ui .tr-l{text-align:right}.swagger-ui .tc-l{text-align:center}.swagger-ui .tj-l{text-align:justify}}.swagger-ui .ttc{text-transform:capitalize}.swagger-ui .ttl{text-transform:lowercase}.swagger-ui .ttu{text-transform:uppercase}.swagger-ui .ttn{text-transform:none}@media screen and (min-width:30em){.swagger-ui .ttc-ns{text-transform:capitalize}.swagger-ui .ttl-ns{text-transform:lowercase}.swagger-ui .ttu-ns{text-transform:uppercase}.swagger-ui .ttn-ns{text-transform:none}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .ttc-m{text-transform:capitalize}.swagger-ui .ttl-m{text-transform:lowercase}.swagger-ui .ttu-m{text-transform:uppercase}.swagger-ui .ttn-m{text-transform:none}}@media screen and (min-width:60em){.swagger-ui .ttc-l{text-transform:capitalize}.swagger-ui .ttl-l{text-transform:lowercase}.swagger-ui .ttu-l{text-transform:uppercase}.swagger-ui .ttn-l{text-transform:none}}.swagger-ui .f-6,.swagger-ui .f-headline{font-size:6rem}.swagger-ui .f-5,.swagger-ui .f-subheadline{font-size:5rem}.swagger-ui .f1{font-size:3rem}.swagger-ui .f2{font-size:2.25rem}.swagger-ui .f3{font-size:1.5rem}.swagger-ui .f4{font-size:1.25rem}.swagger-ui .f5{font-size:1rem}.swagger-ui .f6{font-size:.875rem}.swagger-ui .f7{font-size:.75rem}@media screen and (min-width:30em){.swagger-ui .f-6-ns,.swagger-ui .f-headline-ns{font-size:6rem}.swagger-ui .f-5-ns,.swagger-ui .f-subheadline-ns{font-size:5rem}.swagger-ui .f1-ns{font-size:3rem}.swagger-ui .f2-ns{font-size:2.25rem}.swagger-ui .f3-ns{font-size:1.5rem}.swagger-ui .f4-ns{font-size:1.25rem}.swagger-ui .f5-ns{font-size:1rem}.swagger-ui .f6-ns{font-size:.875rem}.swagger-ui .f7-ns{font-size:.75rem}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .f-6-m,.swagger-ui .f-headline-m{font-size:6rem}.swagger-ui .f-5-m,.swagger-ui .f-subheadline-m{font-size:5rem}.swagger-ui .f1-m{font-size:3rem}.swagger-ui .f2-m{font-size:2.25rem}.swagger-ui .f3-m{font-size:1.5rem}.swagger-ui .f4-m{font-size:1.25rem}.swagger-ui .f5-m{font-size:1rem}.swagger-ui .f6-m{font-size:.875rem}.swagger-ui .f7-m{font-size:.75rem}}@media screen and (min-width:60em){.swagger-ui .f-6-l,.swagger-ui .f-headline-l{font-size:6rem}.swagger-ui .f-5-l,.swagger-ui .f-subheadline-l{font-size:5rem}.swagger-ui .f1-l{font-size:3rem}.swagger-ui .f2-l{font-size:2.25rem}.swagger-ui .f3-l{font-size:1.5rem}.swagger-ui .f4-l{font-size:1.25rem}.swagger-ui .f5-l{font-size:1rem}.swagger-ui .f6-l{font-size:.875rem}.swagger-ui .f7-l{font-size:.75rem}}.swagger-ui .measure{max-width:30em}.swagger-ui .measure-wide{max-width:34em}.swagger-ui .measure-narrow{max-width:20em}.swagger-ui .indent{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media screen and (min-width:30em){.swagger-ui .measure-ns{max-width:30em}.swagger-ui .measure-wide-ns{max-width:34em}.swagger-ui .measure-narrow-ns{max-width:20em}.swagger-ui .indent-ns{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-ns{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-ns{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .measure-m{max-width:30em}.swagger-ui .measure-wide-m{max-width:34em}.swagger-ui .measure-narrow-m{max-width:20em}.swagger-ui .indent-m{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-m{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-m{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}@media screen and (min-width:60em){.swagger-ui .measure-l{max-width:30em}.swagger-ui .measure-wide-l{max-width:34em}.swagger-ui .measure-narrow-l{max-width:20em}.swagger-ui .indent-l{margin-bottom:0;margin-top:0;text-indent:1em}.swagger-ui .small-caps-l{font-feature-settings:"smcp";font-variant:small-caps}.swagger-ui .truncate-l{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}.swagger-ui .overflow-container{overflow-y:scroll}.swagger-ui .center{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto{margin-right:auto}.swagger-ui .ml-auto{margin-left:auto}@media screen and (min-width:30em){.swagger-ui .center-ns{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-ns{margin-right:auto}.swagger-ui .ml-auto-ns{margin-left:auto}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .center-m{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-m{margin-right:auto}.swagger-ui .ml-auto-m{margin-left:auto}}@media screen and (min-width:60em){.swagger-ui .center-l{margin-left:auto;margin-right:auto}.swagger-ui .mr-auto-l{margin-right:auto}.swagger-ui .ml-auto-l{margin-left:auto}}.swagger-ui .clip{position:fixed!important;_position:absolute!important}.swagger-ui .clip{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}@media screen and (min-width:30em){.swagger-ui .clip-ns{position:fixed!important;_position:absolute!important}.swagger-ui .clip-ns{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .clip-m{position:fixed!important;_position:absolute!important}.swagger-ui .clip-m{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}@media screen and (min-width:60em){.swagger-ui .clip-l{position:fixed!important;_position:absolute!important}.swagger-ui .clip-l{clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}}.swagger-ui .ws-normal{white-space:normal}.swagger-ui .nowrap{white-space:nowrap}.swagger-ui .pre{white-space:pre}@media screen and (min-width:30em){.swagger-ui .ws-normal-ns{white-space:normal}.swagger-ui .nowrap-ns{white-space:nowrap}.swagger-ui .pre-ns{white-space:pre}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .ws-normal-m{white-space:normal}.swagger-ui .nowrap-m{white-space:nowrap}.swagger-ui .pre-m{white-space:pre}}@media screen and (min-width:60em){.swagger-ui .ws-normal-l{white-space:normal}.swagger-ui .nowrap-l{white-space:nowrap}.swagger-ui .pre-l{white-space:pre}}.swagger-ui .v-base{vertical-align:baseline}.swagger-ui .v-mid{vertical-align:middle}.swagger-ui .v-top{vertical-align:top}.swagger-ui .v-btm{vertical-align:bottom}@media screen and (min-width:30em){.swagger-ui .v-base-ns{vertical-align:baseline}.swagger-ui .v-mid-ns{vertical-align:middle}.swagger-ui .v-top-ns{vertical-align:top}.swagger-ui .v-btm-ns{vertical-align:bottom}}@media screen and (min-width:30em)and (max-width:60em){.swagger-ui .v-base-m{vertical-align:baseline}.swagger-ui .v-mid-m{vertical-align:middle}.swagger-ui .v-top-m{vertical-align:top}.swagger-ui .v-btm-m{vertical-align:bottom}}@media screen and (min-width:60em){.swagger-ui .v-base-l{vertical-align:baseline}.swagger-ui .v-mid-l{vertical-align:middle}.swagger-ui .v-top-l{vertical-align:top}.swagger-ui .v-btm-l{vertical-align:bottom}}.swagger-ui .dim{opacity:1;transition:opacity .15s ease-in}.swagger-ui .dim:focus,.swagger-ui .dim:hover{opacity:.5;transition:opacity .15s ease-in}.swagger-ui .dim:active{opacity:.8;transition:opacity .15s ease-out}.swagger-ui .glow{transition:opacity .15s ease-in}.swagger-ui .glow:focus,.swagger-ui .glow:hover{opacity:1;transition:opacity .15s ease-in}.swagger-ui .hide-child .child{opacity:0;transition:opacity .15s ease-in}.swagger-ui .hide-child:active .child,.swagger-ui .hide-child:focus .child,.swagger-ui .hide-child:hover .child{opacity:1;transition:opacity .15s ease-in}.swagger-ui .underline-hover:focus,.swagger-ui .underline-hover:hover{-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .grow{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;transform:translateZ(0);transition:transform .25s ease-out}.swagger-ui .grow:focus,.swagger-ui .grow:hover{transform:scale(1.05)}.swagger-ui .grow:active{transform:scale(.9)}.swagger-ui .grow-large{-moz-osx-font-smoothing:grayscale;-webkit-backface-visibility:hidden;backface-visibility:hidden;transform:translateZ(0);transition:transform .25s ease-in-out}.swagger-ui .grow-large:focus,.swagger-ui .grow-large:hover{transform:scale(1.2)}.swagger-ui .grow-large:active{transform:scale(.95)}.swagger-ui .pointer:hover{cursor:pointer}.swagger-ui .shadow-hover{cursor:pointer;position:relative;transition:all .5s cubic-bezier(.165,.84,.44,1)}.swagger-ui .shadow-hover:after{border-radius:inherit;box-shadow:0 0 16px 2px rgba(0,0,0,.2);content:"";height:100%;left:0;opacity:0;position:absolute;top:0;transition:opacity .5s cubic-bezier(.165,.84,.44,1);width:100%;z-index:-1}.swagger-ui .shadow-hover:focus:after,.swagger-ui .shadow-hover:hover:after{opacity:1}.swagger-ui .bg-animate,.swagger-ui .bg-animate:focus,.swagger-ui .bg-animate:hover{transition:background-color .15s ease-in-out}.swagger-ui .z-0{z-index:0}.swagger-ui .z-1{z-index:1}.swagger-ui .z-2{z-index:2}.swagger-ui .z-3{z-index:3}.swagger-ui .z-4{z-index:4}.swagger-ui .z-5{z-index:5}.swagger-ui .z-999{z-index:999}.swagger-ui .z-9999{z-index:9999}.swagger-ui .z-max{z-index:2147483647}.swagger-ui .z-inherit{z-index:inherit}.swagger-ui .z-initial,.swagger-ui .z-unset{z-index:auto}.swagger-ui .nested-copy-line-height ol,.swagger-ui .nested-copy-line-height p,.swagger-ui .nested-copy-line-height ul{line-height:1.5}.swagger-ui .nested-headline-line-height h1,.swagger-ui .nested-headline-line-height h2,.swagger-ui .nested-headline-line-height h3,.swagger-ui .nested-headline-line-height h4,.swagger-ui .nested-headline-line-height h5,.swagger-ui .nested-headline-line-height h6{line-height:1.25}.swagger-ui .nested-list-reset ol,.swagger-ui .nested-list-reset ul{list-style-type:none;margin-left:0;padding-left:0}.swagger-ui .nested-copy-indent p+p{margin-bottom:0;margin-top:0;text-indent:.1em}.swagger-ui .nested-copy-seperator p+p{margin-top:1.5em}.swagger-ui .nested-img img{display:block;max-width:100%;width:100%}.swagger-ui .nested-links a{color:#357edd;transition:color .15s ease-in}.swagger-ui .nested-links a:focus,.swagger-ui .nested-links a:hover{color:#96ccff;transition:color .15s ease-in}.swagger-ui .wrapper{box-sizing:border-box;margin:0 auto;max-width:1460px;padding:0 20px;width:100%}.swagger-ui .opblock-tag-section{display:flex;flex-direction:column}.swagger-ui .try-out.btn-group{display:flex;flex:.1 2 auto;padding:0}.swagger-ui .try-out__btn{margin-left:1.25rem}.swagger-ui .opblock-tag{align-items:center;border-bottom:1px solid rgba(59,65,81,.3);cursor:pointer;display:flex;padding:10px 20px 10px 10px;transition:all .2s}.swagger-ui .opblock-tag:hover{background:rgba(0,0,0,.02)}.swagger-ui .opblock-tag{color:#3b4151;font-family:sans-serif;font-size:24px;margin:0 0 5px}.swagger-ui .opblock-tag.no-desc span{flex:1}.swagger-ui .opblock-tag svg{transition:all .4s}.swagger-ui .opblock-tag small{color:#3b4151;flex:2;font-family:sans-serif;font-size:14px;font-weight:400;padding:0 10px}.swagger-ui .opblock-tag>div{flex:1 1 150px;font-weight:400;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(max-width:640px){.swagger-ui .opblock-tag small,.swagger-ui .opblock-tag>div{flex:1}}.swagger-ui .opblock-tag .info__externaldocs{text-align:right}.swagger-ui .parameter__type{color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;padding:5px 0}.swagger-ui .parameter-controls{margin-top:.75em}.swagger-ui .examples__title{display:block;font-size:1.1em;font-weight:700;margin-bottom:.75em}.swagger-ui .examples__section{margin-top:1.5em}.swagger-ui .examples__section-header{font-size:.9rem;font-weight:700;margin-bottom:.5rem}.swagger-ui .examples-select{display:inline-block;margin-bottom:.75em}.swagger-ui .examples-select .examples-select-element{width:100%}.swagger-ui .examples-select__section-label{font-size:.9rem;font-weight:700;margin-right:.5rem}.swagger-ui .example__section{margin-top:1.5em}.swagger-ui .example__section-header{font-size:.9rem;font-weight:700;margin-bottom:.5rem}.swagger-ui .view-line-link{cursor:pointer;margin:0 5px;position:relative;top:3px;transition:all .5s;width:20px}.swagger-ui .opblock{border:1px solid #000;border-radius:4px;box-shadow:0 0 3px rgba(0,0,0,.19);margin:0 0 15px}.swagger-ui .opblock .tab-header{display:flex;flex:1}.swagger-ui .opblock .tab-header .tab-item{cursor:pointer;padding:0 40px}.swagger-ui .opblock .tab-header .tab-item:first-of-type{padding:0 40px 0 0}.swagger-ui .opblock .tab-header .tab-item.active h4 span{position:relative}.swagger-ui .opblock .tab-header .tab-item.active h4 span:after{background:gray;bottom:-15px;content:"";height:4px;left:50%;position:absolute;transform:translateX(-50%);width:120%}.swagger-ui .opblock.is-open .opblock-summary{border-bottom:1px solid #000}.swagger-ui .opblock .opblock-section-header{align-items:center;background:hsla(0,0%,100%,.8);box-shadow:0 1px 2px rgba(0,0,0,.1);display:flex;min-height:50px;padding:8px 20px}.swagger-ui .opblock .opblock-section-header>label{align-items:center;color:#3b4151;display:flex;font-family:sans-serif;font-size:12px;font-weight:700;margin:0 0 0 auto}.swagger-ui .opblock .opblock-section-header>label>span{padding:0 10px 0 0}.swagger-ui .opblock .opblock-section-header h4{color:#3b4151;flex:1;font-family:sans-serif;font-size:14px;margin:0}.swagger-ui .opblock .opblock-summary-method{background:#000;border-radius:3px;color:#fff;font-family:sans-serif;font-size:14px;font-weight:700;min-width:80px;padding:6px 0;text-align:center;text-shadow:0 1px 0 rgba(0,0,0,.1)}.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{align-items:center;color:#3b4151;display:flex;font-family:monospace;font-size:16px;font-weight:600;padding:0 10px;word-break:break-word}@media(max-width:768px){.swagger-ui .opblock .opblock-summary-operation-id,.swagger-ui .opblock .opblock-summary-path,.swagger-ui .opblock .opblock-summary-path__deprecated{font-size:12px}}.swagger-ui .opblock .opblock-summary-path{flex-shrink:0;max-width:calc(100% - 110px - 15rem)}@media(max-width:640px){.swagger-ui .opblock .opblock-summary-path{flex-shrink:1;max-width:100%}}.swagger-ui .opblock .opblock-summary-path__deprecated{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .opblock .opblock-summary-operation-id{font-size:14px}.swagger-ui .opblock .opblock-summary-description{color:#3b4151;flex:1 1 auto;font-family:sans-serif;font-size:13px;word-break:break-word}.swagger-ui .opblock .opblock-summary{align-items:center;cursor:pointer;display:flex;padding:5px}.swagger-ui .opblock .opblock-summary .view-line-link{cursor:pointer;margin:0;position:relative;top:2px;transition:all .5s;width:0}.swagger-ui .opblock .opblock-summary:hover .view-line-link{margin:0 5px;width:18px}.swagger-ui .opblock .opblock-summary:hover .view-line-link.copy-to-clipboard{width:24px}.swagger-ui .opblock.opblock-post{background:rgba(73,204,144,.1);border-color:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary-method{background:#49cc90}.swagger-ui .opblock.opblock-post .opblock-summary{border-color:#49cc90}.swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span:after{background:#49cc90}.swagger-ui .opblock.opblock-put{background:rgba(252,161,48,.1);border-color:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary-method{background:#fca130}.swagger-ui .opblock.opblock-put .opblock-summary{border-color:#fca130}.swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span:after{background:#fca130}.swagger-ui .opblock.opblock-delete{background:rgba(249,62,62,.1);border-color:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary-method{background:#f93e3e}.swagger-ui .opblock.opblock-delete .opblock-summary{border-color:#f93e3e}.swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span:after{background:#f93e3e}.swagger-ui .opblock.opblock-get{background:rgba(97,175,254,.1);border-color:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary-method{background:#61affe}.swagger-ui .opblock.opblock-get .opblock-summary{border-color:#61affe}.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span:after{background:#61affe}.swagger-ui .opblock.opblock-patch{background:rgba(80,227,194,.1);border-color:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary-method{background:#50e3c2}.swagger-ui .opblock.opblock-patch .opblock-summary{border-color:#50e3c2}.swagger-ui .opblock.opblock-patch .tab-header .tab-item.active h4 span:after{background:#50e3c2}.swagger-ui .opblock.opblock-head{background:rgba(144,18,254,.1);border-color:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary-method{background:#9012fe}.swagger-ui .opblock.opblock-head .opblock-summary{border-color:#9012fe}.swagger-ui .opblock.opblock-head .tab-header .tab-item.active h4 span:after{background:#9012fe}.swagger-ui .opblock.opblock-options{background:rgba(13,90,167,.1);border-color:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary-method{background:#0d5aa7}.swagger-ui .opblock.opblock-options .opblock-summary{border-color:#0d5aa7}.swagger-ui .opblock.opblock-options .tab-header .tab-item.active h4 span:after{background:#0d5aa7}.swagger-ui .opblock.opblock-deprecated{background:hsla(0,0%,92%,.1);border-color:#ebebeb;opacity:.6}.swagger-ui .opblock.opblock-deprecated .opblock-summary-method{background:#ebebeb}.swagger-ui .opblock.opblock-deprecated .opblock-summary{border-color:#ebebeb}.swagger-ui .opblock.opblock-deprecated .tab-header .tab-item.active h4 span:after{background:#ebebeb}.swagger-ui .opblock .opblock-schemes{padding:8px 20px}.swagger-ui .opblock .opblock-schemes .schemes-title{padding:0 10px 0 0}.swagger-ui .filter .operation-filter-input{border:2px solid #d8dde7;margin:20px 0;padding:10px;width:100%}.swagger-ui .download-url-wrapper .failed,.swagger-ui .filter .failed{color:red}.swagger-ui .download-url-wrapper .loading,.swagger-ui .filter .loading{color:#aaa}.swagger-ui .model-example{margin-top:1em}.swagger-ui .tab{display:flex;list-style:none;padding:0}.swagger-ui .tab li{color:#3b4151;cursor:pointer;font-family:sans-serif;font-size:12px;min-width:60px;padding:0}.swagger-ui .tab li:first-of-type{padding-left:0;padding-right:12px;position:relative}.swagger-ui .tab li:first-of-type:after{background:rgba(0,0,0,.2);content:"";height:100%;position:absolute;right:6px;top:0;width:1px}.swagger-ui .tab li.active{font-weight:700}.swagger-ui .tab li button.tablinks{background:none;border:0;color:inherit;font-family:inherit;font-weight:inherit;padding:0}.swagger-ui .opblock-description-wrapper,.swagger-ui .opblock-external-docs-wrapper,.swagger-ui .opblock-title_normal{color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px;padding:15px 20px}.swagger-ui .opblock-description-wrapper h4,.swagger-ui .opblock-external-docs-wrapper h4,.swagger-ui .opblock-title_normal h4{color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px}.swagger-ui .opblock-description-wrapper p,.swagger-ui .opblock-external-docs-wrapper p,.swagger-ui .opblock-title_normal p{color:#3b4151;font-family:sans-serif;font-size:14px;margin:0}.swagger-ui .opblock-external-docs-wrapper h4{padding-left:0}.swagger-ui .execute-wrapper{padding:20px;text-align:right}.swagger-ui .execute-wrapper .btn{padding:8px 40px;width:100%}.swagger-ui .body-param-options{display:flex;flex-direction:column}.swagger-ui .body-param-options .body-param-edit{padding:10px 0}.swagger-ui .body-param-options label{padding:8px 0}.swagger-ui .body-param-options label select{margin:3px 0 0}.swagger-ui .responses-inner{padding:20px}.swagger-ui .responses-inner h4,.swagger-ui .responses-inner h5{color:#3b4151;font-family:sans-serif;font-size:12px;margin:10px 0 5px}.swagger-ui .responses-inner .curl{white-space:normal}.swagger-ui .response-col_status{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .response-col_status .response-undocumented{color:#909090;font-family:monospace;font-size:11px;font-weight:600}.swagger-ui .response-col_links{color:#3b4151;font-family:sans-serif;font-size:14px;max-width:40em;padding-left:2em}.swagger-ui .response-col_links .response-undocumented{color:#909090;font-family:monospace;font-size:11px;font-weight:600}.swagger-ui .response-col_links .operation-link{margin-bottom:1.5em}.swagger-ui .response-col_links .operation-link .description{margin-bottom:.5em}.swagger-ui .opblock-body .opblock-loading-animation{display:block;margin:3em auto}.swagger-ui .opblock-body pre.microlight{word-wrap:break-word;background:#333;border-radius:4px;color:#fff;font-family:monospace;font-size:12px;font-weight:600;-webkit-hyphens:auto;hyphens:auto;margin:0;padding:10px;white-space:pre-wrap;word-break:break-all;word-break:break-word}.swagger-ui .opblock-body pre.microlight .headerline{display:block}.swagger-ui .highlight-code{position:relative}.swagger-ui .highlight-code>.microlight{max-height:400px;min-height:6em;overflow-y:auto}.swagger-ui .highlight-code>.microlight code{white-space:pre-wrap!important}.swagger-ui .highlight-code>.microlight code{word-break:break-all}.swagger-ui .curl-command{position:relative}.swagger-ui .download-contents{align-items:center;background:#7d8293;border-radius:4px;bottom:10px;color:#fff;cursor:pointer;display:flex;font-family:sans-serif;font-size:14px;font-weight:600;height:30px;justify-content:center;padding:5px;position:absolute;right:10px;text-align:center}.swagger-ui .scheme-container{background:#fff;box-shadow:0 1px 2px 0 rgba(0,0,0,.15);margin:0 0 20px;padding:30px 0}.swagger-ui .scheme-container .schemes{align-items:flex-end;display:flex}.swagger-ui .scheme-container .schemes>label{color:#3b4151;display:flex;flex-direction:column;font-family:sans-serif;font-size:12px;font-weight:700;margin:-20px 15px 0 0}.swagger-ui .scheme-container .schemes>label select{min-width:130px;text-transform:uppercase}.swagger-ui .loading-container{align-items:center;display:flex;flex-direction:column;justify-content:center;margin-top:1em;min-height:1px;padding:40px 0 60px}.swagger-ui .loading-container .loading{position:relative}.swagger-ui .loading-container .loading:after{color:#3b4151;content:"loading";font-family:sans-serif;font-size:10px;font-weight:700;left:50%;position:absolute;text-transform:uppercase;top:50%;transform:translate(-50%,-50%)}.swagger-ui .loading-container .loading:before{animation:rotation 1s linear infinite,opacity .5s;-webkit-backface-visibility:hidden;backface-visibility:hidden;border:2px solid rgba(85,85,85,.1);border-radius:100%;border-top-color:rgba(0,0,0,.6);content:"";display:block;height:60px;left:50%;margin:-30px;opacity:1;position:absolute;top:50%;width:60px}@keyframes rotation{to{transform:rotate(1turn)}}.swagger-ui .response-controls{display:flex;padding-top:1em}.swagger-ui .response-control-media-type{margin-right:1em}.swagger-ui .response-control-media-type--accept-controller select{border-color:green}.swagger-ui .response-control-media-type__accept-message{color:green;font-size:.7em}.swagger-ui .response-control-examples__title,.swagger-ui .response-control-media-type__title{display:block;font-size:.7em;margin-bottom:.2em}@keyframes blinker{50%{opacity:0}}.swagger-ui .hidden{display:none}.swagger-ui .no-margin{border:none;height:auto;margin:0;padding:0}.swagger-ui .float-right{float:right}.swagger-ui .svg-assets{height:0;position:absolute;width:0}.swagger-ui section h3{color:#3b4151;font-family:sans-serif}.swagger-ui a.nostyle{display:inline}.swagger-ui a.nostyle,.swagger-ui a.nostyle:visited{color:inherit;cursor:pointer;text-decoration:inherit}.swagger-ui .fallback{color:#aaa;padding:1em}.swagger-ui .version-pragma{height:100%;padding:5em 0}.swagger-ui .version-pragma__message{display:flex;font-size:1.2em;height:100%;justify-content:center;line-height:1.5em;padding:0 .6em;text-align:center}.swagger-ui .version-pragma__message>div{flex:1;max-width:55ch}.swagger-ui .version-pragma__message code{background-color:#dedede;padding:4px 4px 2px;white-space:pre}.swagger-ui .opblock-link{font-weight:400}.swagger-ui .opblock-link.shown{font-weight:700}.swagger-ui span.token-string{color:#555}.swagger-ui span.token-not-formatted{color:#555;font-weight:700}.swagger-ui .btn{background:transparent;border:2px solid gray;border-radius:4px;box-shadow:0 1px 2px rgba(0,0,0,.1);color:#3b4151;font-family:sans-serif;font-size:14px;font-weight:700;padding:5px 23px;transition:all .3s}.swagger-ui .btn.btn-sm{font-size:12px;padding:4px 23px}.swagger-ui .btn[disabled]{cursor:not-allowed;opacity:.3}.swagger-ui .btn:hover{box-shadow:0 0 5px rgba(0,0,0,.3)}.swagger-ui .btn.cancel{background-color:transparent;border-color:#ff6060;color:#ff6060;font-family:sans-serif}.swagger-ui .btn.authorize{background-color:transparent;border-color:#49cc90;color:#49cc90;display:inline;line-height:1}.swagger-ui .btn.authorize span{float:left;padding:4px 20px 0 0}.swagger-ui .btn.authorize svg{fill:#49cc90}.swagger-ui .btn.execute{background-color:#4990e2;border-color:#4990e2;color:#fff}.swagger-ui .btn-group{display:flex;padding:30px}.swagger-ui .btn-group .btn{flex:1}.swagger-ui .btn-group .btn:first-child{border-radius:4px 0 0 4px}.swagger-ui .btn-group .btn:last-child{border-radius:0 4px 4px 0}.swagger-ui .authorization__btn{background:none;border:none;padding:0 0 0 10px}.swagger-ui .authorization__btn.locked{opacity:1}.swagger-ui .authorization__btn.unlocked{opacity:.4}.swagger-ui .model-box-control,.swagger-ui .models-control,.swagger-ui .opblock-summary-control{all:inherit;border-bottom:0;cursor:pointer;flex:1;padding:0}.swagger-ui .model-box-control:focus,.swagger-ui .models-control:focus,.swagger-ui .opblock-summary-control:focus{outline:auto}.swagger-ui .expand-methods,.swagger-ui .expand-operation{background:none;border:none}.swagger-ui .expand-methods svg,.swagger-ui .expand-operation svg{height:20px;width:20px}.swagger-ui .expand-methods{padding:0 10px}.swagger-ui .expand-methods:hover svg{fill:#404040}.swagger-ui .expand-methods svg{fill:#707070;transition:all .3s}.swagger-ui button{cursor:pointer}.swagger-ui button.invalid{animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui .copy-to-clipboard{align-items:center;background:#7d8293;border:none;border-radius:4px;bottom:10px;display:flex;height:30px;justify-content:center;position:absolute;right:100px;width:30px}.swagger-ui .copy-to-clipboard button{background:url("data:image/svg+xml;charset=utf-8,") 50% no-repeat;border:none;flex-grow:1;flex-shrink:1;height:25px}.swagger-ui .curl-command .copy-to-clipboard{bottom:5px;height:20px;right:10px;width:20px}.swagger-ui .curl-command .copy-to-clipboard button{height:18px}.swagger-ui .opblock .opblock-summary .view-line-link.copy-to-clipboard{height:26px;position:static}.swagger-ui select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#f7f7f7 url("data:image/svg+xml;charset=utf-8,") right 10px center no-repeat;background-size:20px;border:2px solid #41444e;border-radius:4px;box-shadow:0 1px 2px 0 rgba(0,0,0,.25);color:#3b4151;font-family:sans-serif;font-size:14px;font-weight:700;padding:5px 40px 5px 10px}.swagger-ui select[multiple]{background:#f7f7f7;margin:5px 0;padding:5px}.swagger-ui select.invalid{animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui .opblock-body select{min-width:230px}@media(max-width:768px){.swagger-ui .opblock-body select{min-width:180px}}@media(max-width:640px){.swagger-ui .opblock-body select{min-width:100%;width:100%}}.swagger-ui label{color:#3b4151;font-family:sans-serif;font-size:12px;font-weight:700;margin:0 0 5px}.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text]{line-height:1}@media(max-width:768px){.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text]{max-width:175px}}.swagger-ui input[type=email],.swagger-ui input[type=file],.swagger-ui input[type=password],.swagger-ui input[type=search],.swagger-ui input[type=text],.swagger-ui textarea{background:#fff;border:1px solid #d9d9d9;border-radius:4px;margin:5px 0;min-width:100px;padding:8px 10px}.swagger-ui input[type=email].invalid,.swagger-ui input[type=file].invalid,.swagger-ui input[type=password].invalid,.swagger-ui input[type=search].invalid,.swagger-ui input[type=text].invalid,.swagger-ui textarea.invalid{animation:shake .4s 1;background:#feebeb;border-color:#f93e3e}.swagger-ui input[disabled],.swagger-ui select[disabled],.swagger-ui textarea[disabled]{background-color:#fafafa;color:#888;cursor:not-allowed}.swagger-ui select[disabled]{border-color:#888}.swagger-ui textarea[disabled]{background-color:#41444e;color:#fff}@keyframes shake{10%,90%{transform:translate3d(-1px,0,0)}20%,80%{transform:translate3d(2px,0,0)}30%,50%,70%{transform:translate3d(-4px,0,0)}40%,60%{transform:translate3d(4px,0,0)}}.swagger-ui textarea{background:hsla(0,0%,100%,.8);border:none;border-radius:4px;color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;min-height:280px;outline:none;padding:10px;width:100%}.swagger-ui textarea:focus{border:2px solid #61affe}.swagger-ui textarea.curl{background:#41444e;border-radius:4px;color:#fff;font-family:monospace;font-size:12px;font-weight:600;margin:0;min-height:100px;padding:10px;resize:none}.swagger-ui .checkbox{color:#303030;padding:5px 0 10px;transition:opacity .5s}.swagger-ui .checkbox label{display:flex}.swagger-ui .checkbox p{font-weight:400!important;margin:0!important}.swagger-ui .checkbox p{color:#3b4151;font-family:monospace;font-style:italic;font-weight:600}.swagger-ui .checkbox input[type=checkbox]{display:none}.swagger-ui .checkbox input[type=checkbox]+label>.item{background:#e8e8e8;border-radius:1px;box-shadow:0 0 0 2px #e8e8e8;cursor:pointer;display:inline-block;flex:none;height:16px;margin:0 8px 0 0;padding:5px;position:relative;top:3px;width:16px}.swagger-ui .checkbox input[type=checkbox]+label>.item:active{transform:scale(.9)}.swagger-ui .checkbox input[type=checkbox]:checked+label>.item{background:#e8e8e8 url("data:image/svg+xml;charset=utf-8,") 50% no-repeat}.swagger-ui .dialog-ux{bottom:0;left:0;position:fixed;right:0;top:0;z-index:9999}.swagger-ui .dialog-ux .backdrop-ux{background:rgba(0,0,0,.8);bottom:0;left:0;position:fixed;right:0;top:0}.swagger-ui .dialog-ux .modal-ux{background:#fff;border:1px solid #ebebeb;border-radius:4px;box-shadow:0 10px 30px 0 rgba(0,0,0,.2);left:50%;max-width:650px;min-width:300px;position:absolute;top:50%;transform:translate(-50%,-50%);width:100%;z-index:9999}.swagger-ui .dialog-ux .modal-ux-content{max-height:540px;overflow-y:auto;padding:20px}.swagger-ui .dialog-ux .modal-ux-content p{color:#41444e;color:#3b4151;font-family:sans-serif;font-size:12px;margin:0 0 5px}.swagger-ui .dialog-ux .modal-ux-content h4{color:#3b4151;font-family:sans-serif;font-size:18px;font-weight:600;margin:15px 0 0}.swagger-ui .dialog-ux .modal-ux-header{align-items:center;border-bottom:1px solid #ebebeb;display:flex;padding:12px 0}.swagger-ui .dialog-ux .modal-ux-header .close-modal{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;padding:0 10px}.swagger-ui .dialog-ux .modal-ux-header h3{color:#3b4151;flex:1;font-family:sans-serif;font-size:20px;font-weight:600;margin:0;padding:0 20px}.swagger-ui .model{color:#3b4151;font-family:monospace;font-size:12px;font-weight:300;font-weight:600}.swagger-ui .model .deprecated span,.swagger-ui .model .deprecated td{color:#a0a0a0!important}.swagger-ui .model .deprecated>td:first-of-type{-webkit-text-decoration:line-through;text-decoration:line-through}.swagger-ui .model-toggle{cursor:pointer;display:inline-block;font-size:10px;margin:auto .3em;position:relative;top:6px;transform:rotate(90deg);transform-origin:50% 50%;transition:transform .15s ease-in}.swagger-ui .model-toggle.collapsed{transform:rotate(0deg)}.swagger-ui .model-toggle:after{background:url("data:image/svg+xml;charset=utf-8,") 50% no-repeat;background-size:100%;content:"";display:block;height:20px;width:20px}.swagger-ui .model-jump-to-path{cursor:pointer;position:relative}.swagger-ui .model-jump-to-path .view-line-link{cursor:pointer;position:absolute;top:-.4em}.swagger-ui .model-title{position:relative}.swagger-ui .model-title:hover .model-hint{visibility:visible}.swagger-ui .model-hint{background:rgba(0,0,0,.7);border-radius:4px;color:#ebebeb;padding:.1em .5em;position:absolute;top:-1.8em;visibility:hidden;white-space:nowrap}.swagger-ui .model p{margin:0 0 1em}.swagger-ui .model .property{color:#999;font-style:italic}.swagger-ui .model .property.primitive{color:#6b6b6b}.swagger-ui .model .external-docs,.swagger-ui table.model tr.description{color:#666;font-weight:400}.swagger-ui table.model tr.description td:first-child,.swagger-ui table.model tr.property-row.required td:first-child{font-weight:700}.swagger-ui table.model tr.property-row td{vertical-align:top}.swagger-ui table.model tr.property-row td:first-child{padding-right:.2em}.swagger-ui table.model tr.property-row .star{color:red}.swagger-ui table.model tr.extension{color:#777}.swagger-ui table.model tr.extension td:last-child{vertical-align:top}.swagger-ui table.model tr.external-docs td:first-child{font-weight:700}.swagger-ui table.model tr .renderedMarkdown p:first-child{margin-top:0}.swagger-ui section.models{border:1px solid rgba(59,65,81,.3);border-radius:4px;margin:30px 0}.swagger-ui section.models .pointer{cursor:pointer}.swagger-ui section.models.is-open{padding:0 0 20px}.swagger-ui section.models.is-open h4{border-bottom:1px solid rgba(59,65,81,.3);margin:0 0 5px}.swagger-ui section.models h4{align-items:center;color:#606060;cursor:pointer;display:flex;font-family:sans-serif;font-size:16px;margin:0;padding:10px 20px 10px 10px;transition:all .2s}.swagger-ui section.models h4 svg{transition:all .4s}.swagger-ui section.models h4 span{flex:1}.swagger-ui section.models h4:hover{background:rgba(0,0,0,.02)}.swagger-ui section.models h5{color:#707070;font-family:sans-serif;font-size:16px;margin:0 0 10px}.swagger-ui section.models .model-jump-to-path{position:relative;top:5px}.swagger-ui section.models .model-container{background:rgba(0,0,0,.05);border-radius:4px;margin:0 20px 15px;position:relative;transition:all .5s}.swagger-ui section.models .model-container:hover{background:rgba(0,0,0,.07)}.swagger-ui section.models .model-container:first-of-type{margin:20px}.swagger-ui section.models .model-container:last-of-type{margin:0 20px}.swagger-ui section.models .model-container .models-jump-to-path{opacity:.65;position:absolute;right:5px;top:8px}.swagger-ui section.models .model-box{background:none}.swagger-ui .model-box{background:rgba(0,0,0,.1);border-radius:4px;display:inline-block;padding:10px}.swagger-ui .model-box .model-jump-to-path{position:relative;top:4px}.swagger-ui .model-box.deprecated{opacity:.5}.swagger-ui .model-title{color:#505050;font-family:sans-serif;font-size:16px}.swagger-ui .model-title img{bottom:0;margin-left:1em;position:relative}.swagger-ui .model-deprecated-warning{color:#f93e3e;font-family:sans-serif;font-size:16px;font-weight:600;margin-right:1em}.swagger-ui span>span.model .brace-close{padding:0 0 0 10px}.swagger-ui .prop-name{display:inline-block;margin-right:1em}.swagger-ui .prop-type{color:#55a}.swagger-ui .prop-enum{display:block}.swagger-ui .prop-format{color:#606060}.swagger-ui .servers>label{color:#3b4151;font-family:sans-serif;font-size:12px;margin:-20px 15px 0 0}.swagger-ui .servers>label select{max-width:100%;min-width:130px;width:100%}.swagger-ui .servers h4.message{padding-bottom:2em}.swagger-ui .servers table tr{width:30em}.swagger-ui .servers table td{display:inline-block;max-width:15em;padding-bottom:10px;padding-top:10px;vertical-align:middle}.swagger-ui .servers table td:first-of-type{padding-right:1em}.swagger-ui .servers table td input{height:100%;width:100%}.swagger-ui .servers .computed-url{margin:2em 0}.swagger-ui .servers .computed-url code{display:inline-block;font-size:16px;margin:0 1em;padding:4px}.swagger-ui .servers-title{font-size:12px;font-weight:700}.swagger-ui .operation-servers h4.message{margin-bottom:2em}.swagger-ui table{border-collapse:collapse;padding:0 10px;width:100%}.swagger-ui table.model tbody tr td{padding:0;vertical-align:top}.swagger-ui table.model tbody tr td:first-of-type{padding:0 0 0 2em;width:174px}.swagger-ui table.headers td{color:#3b4151;font-family:monospace;font-size:12px;font-weight:300;font-weight:600;vertical-align:middle}.swagger-ui table.headers .header-example{color:#999;font-style:italic}.swagger-ui table tbody tr td{padding:10px 0 0;vertical-align:top}.swagger-ui table tbody tr td:first-of-type{min-width:6em;padding:10px 0}.swagger-ui table thead tr td,.swagger-ui table thead tr th{border-bottom:1px solid rgba(59,65,81,.2);color:#3b4151;font-family:sans-serif;font-size:12px;font-weight:700;padding:12px 0;text-align:left}.swagger-ui .parameters-col_description{margin-bottom:2em;width:99%}.swagger-ui .parameters-col_description input{max-width:340px;width:100%}.swagger-ui .parameters-col_description select{border-width:1px}.swagger-ui .parameters-col_description .markdown p{margin:0}.swagger-ui .parameter__name{color:#3b4151;font-family:sans-serif;font-size:16px;font-weight:400;margin-right:.75em}.swagger-ui .parameter__name.required{font-weight:700}.swagger-ui .parameter__name.required span{color:red}.swagger-ui .parameter__name.required:after{color:rgba(255,0,0,.6);content:"required";font-size:10px;padding:5px;position:relative;top:-6px}.swagger-ui .parameter__extension,.swagger-ui .parameter__in{color:gray;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .parameter__deprecated{color:red;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .parameter__empty_value_toggle{display:block;font-size:13px;padding-bottom:12px;padding-top:5px}.swagger-ui .parameter__empty_value_toggle input{margin-right:7px}.swagger-ui .parameter__empty_value_toggle.disabled{opacity:.7}.swagger-ui .table-container{padding:20px}.swagger-ui .response-col_description{width:99%}.swagger-ui .response-col_description .markdown p{margin:0}.swagger-ui .response-col_links{min-width:6em}.swagger-ui .response__extension{color:gray;font-family:monospace;font-size:12px;font-style:italic;font-weight:600}.swagger-ui .topbar{background-color:#1b1b1b;padding:10px 0}.swagger-ui .topbar .topbar-wrapper,.swagger-ui .topbar a{align-items:center;display:flex}.swagger-ui .topbar a{color:#fff;flex:1;font-family:sans-serif;font-size:1.5em;font-weight:700;max-width:300px;-webkit-text-decoration:none;text-decoration:none}.swagger-ui .topbar a span{margin:0;padding:0 10px}.swagger-ui .topbar .download-url-wrapper{display:flex;flex:3;justify-content:flex-end}.swagger-ui .topbar .download-url-wrapper input[type=text]{border:2px solid #62a03f;border-radius:4px 0 0 4px;margin:0;outline:none;width:100%}.swagger-ui .topbar .download-url-wrapper .select-label{align-items:center;color:#f0f0f0;display:flex;margin:0;max-width:600px;width:100%}.swagger-ui .topbar .download-url-wrapper .select-label span{flex:1;font-size:16px;padding:0 10px 0 0;text-align:right}.swagger-ui .topbar .download-url-wrapper .select-label select{border:2px solid #62a03f;box-shadow:none;flex:2;outline:none;width:100%}.swagger-ui .topbar .download-url-wrapper .download-url-button{background:#62a03f;border:none;border-radius:0 4px 4px 0;color:#fff;font-family:sans-serif;font-size:16px;font-weight:700;padding:4px 30px}.swagger-ui .info{margin:50px 0}.swagger-ui .info.failed-config{margin-left:auto;margin-right:auto;max-width:880px;text-align:center}.swagger-ui .info hgroup.main{margin:0 0 20px}.swagger-ui .info hgroup.main a{font-size:12px}.swagger-ui .info pre{font-size:14px}.swagger-ui .info li,.swagger-ui .info p,.swagger-ui .info table{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .info h1,.swagger-ui .info h2,.swagger-ui .info h3,.swagger-ui .info h4,.swagger-ui .info h5{color:#3b4151;font-family:sans-serif}.swagger-ui .info a{color:#4990e2;font-family:sans-serif;font-size:14px;transition:all .4s}.swagger-ui .info a:hover{color:#1f69c0}.swagger-ui .info>div{margin:0 0 5px}.swagger-ui .info .base-url{font-weight:300!important}.swagger-ui .info .base-url{color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;margin:0}.swagger-ui .info .title{color:#3b4151;font-family:sans-serif;font-size:36px;margin:0}.swagger-ui .info .title small{background:#7d8492;border-radius:57px;display:inline-block;font-size:10px;margin:0 0 0 5px;padding:2px 4px;position:relative;top:-5px;vertical-align:super}.swagger-ui .info .title small.version-stamp{background-color:#89bf04}.swagger-ui .info .title small pre{color:#fff;font-family:sans-serif;margin:0;padding:0}.swagger-ui .auth-btn-wrapper{display:flex;justify-content:center;padding:10px 0}.swagger-ui .auth-btn-wrapper .btn-done{margin-right:1em}.swagger-ui .auth-wrapper{display:flex;flex:1;justify-content:flex-end}.swagger-ui .auth-wrapper .authorize{margin-left:10px;margin-right:10px;padding-right:20px}.swagger-ui .auth-container{border-bottom:1px solid #ebebeb;margin:0 0 10px;padding:10px 20px}.swagger-ui .auth-container:last-of-type{border:0;margin:0;padding:10px 20px}.swagger-ui .auth-container h4{margin:5px 0 15px!important}.swagger-ui .auth-container .wrapper{margin:0;padding:0}.swagger-ui .auth-container input[type=password],.swagger-ui .auth-container input[type=text]{min-width:230px}.swagger-ui .auth-container .errors{background-color:#fee;border-radius:4px;color:red;color:#3b4151;font-family:monospace;font-size:12px;font-weight:600;margin:1em;padding:10px}.swagger-ui .auth-container .errors b{margin-right:1em;text-transform:capitalize}.swagger-ui .scopes h2{color:#3b4151;font-family:sans-serif;font-size:14px}.swagger-ui .scopes h2 a{color:#4990e2;cursor:pointer;font-size:12px;padding-left:10px;-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .scope-def{padding:0 0 20px}.swagger-ui .errors-wrapper{animation:scaleUp .5s;background:rgba(249,62,62,.1);border:2px solid #f93e3e;border-radius:4px;margin:20px;padding:10px 20px}.swagger-ui .errors-wrapper .error-wrapper{margin:0 0 10px}.swagger-ui .errors-wrapper .errors h4{color:#3b4151;font-family:monospace;font-size:14px;font-weight:600;margin:0}.swagger-ui .errors-wrapper .errors small{color:#606060}.swagger-ui .errors-wrapper .errors .message{white-space:pre-line}.swagger-ui .errors-wrapper .errors .message.thrown{max-width:100%}.swagger-ui .errors-wrapper .errors .error-line{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.swagger-ui .errors-wrapper hgroup{align-items:center;display:flex}.swagger-ui .errors-wrapper hgroup h4{color:#3b4151;flex:1;font-family:sans-serif;font-size:20px;margin:0}@keyframes scaleUp{0%{opacity:0;transform:scale(.8)}to{opacity:1;transform:scale(1)}}.swagger-ui .Resizer.vertical.disabled{display:none}.swagger-ui .markdown p,.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown p,.swagger-ui .renderedMarkdown pre{margin:1em auto;word-break:break-all;word-break:break-word}.swagger-ui .markdown pre,.swagger-ui .renderedMarkdown pre{background:none;color:#000;font-weight:400;padding:0;white-space:pre-wrap}.swagger-ui .markdown code,.swagger-ui .renderedMarkdown code{background:rgba(0,0,0,.05);border-radius:4px;color:#9012fe;font-family:monospace;font-size:14px;font-weight:600;padding:5px 7px}.swagger-ui .markdown pre>code,.swagger-ui .renderedMarkdown pre>code{display:block} + +/*# sourceMappingURL=swagger-ui.css.map*/ \ No newline at end of file diff --git a/edoc/resources/css/view.css b/edoc/resources/css/view.css index c4458b9a..446a679b 100644 --- a/edoc/resources/css/view.css +++ b/edoc/resources/css/view.css @@ -11,7 +11,7 @@ */ body { - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr; /* this should allow main to grow/shrink and aside with contents to follow */ } /* hide right side on small broser windows, e.g. mobile */ @@ -94,14 +94,10 @@ body > aside { overflow: initial; } -#ann { +aside > div { position: absolute; } -#fac { - height: 100%; -} - q { quotes: "»" "«" "›" "‹"; } @@ -134,12 +130,12 @@ div.footnote { display: table-row; } -/* footnote number within the main text */ +/* footnote number within the main text .fnNumber { font-size: 0.9em; vertical-align: super; line-height: 0; -} +} */ /* footnote number within apparatus */ .footnotes .fnNumber { @@ -171,9 +167,11 @@ div.footnote { /* footnote links */ button[aria-label].footnoteNumber { - vertical-align: super; - font-size: 0.75rem; + display: inline-block; + font-size: 0.9em; line-height: 0; + text-indent: 0; + vertical-align: super; } /* Spans acting as buttons to display entity information */ diff --git a/edoc/resources/css/wdb.css b/edoc/resources/css/wdb.css index 6c53793d..a39e72a8 100644 --- a/edoc/resources/css/wdb.css +++ b/edoc/resources/css/wdb.css @@ -166,6 +166,14 @@ nav ul { list-style-type: none; } +nav li { + display: table-row; +} +li .label { + display: table-cell; + padding-right: 0.5em; +} + nav li ul { margin-left: 1.25em; } diff --git a/edoc/resources/html/.gitkeep b/edoc/resources/html/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/resources/images/.gitkeep b/edoc/resources/images/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/edoc/resources/FhHRx.gif b/edoc/resources/images/FhHRx.gif similarity index 100% rename from edoc/resources/FhHRx.gif rename to edoc/resources/images/FhHRx.gif diff --git a/edoc/resources/scripts/admin.js b/edoc/resources/js/admin.js similarity index 78% rename from edoc/resources/scripts/admin.js rename to edoc/resources/js/admin.js index 763ef34e..c4cd7faf 100644 --- a/edoc/resources/scripts/admin.js +++ b/edoc/resources/js/admin.js @@ -7,37 +7,22 @@ const wdbAdmin = { url: url, cache: false, dataType: "json", - success: function (data) { - this.getPaths(data); + success: function ( data ) { + wdbAdmin.getPaths(); $("input[type='submit']").prop("disabled", false); }, error: function ( response ) { - wdb.report("error", "Kein Projekt mit der ID " + wdb.params.id + " gefunden oder Projekt für den aktuellen Benutzer nicht lesbar.", + wdb.report("error", "Kein Projekt mit der ID " + wdb.parameters.ed + " gefunden oder Projekt für den aktuellen Benutzer nicht lesbar.", response, $('aside')); } }); $('#selectTarget').show(); }, - getPaths: function ( data ) { - if (data instanceof Array) { - data.forEach(function( subcollection ) { - if (subcollection == "texts") { - $('#selectTarget select').append(''); - } else { - $('#selectTarget select').append(""); - } - }); - } else { - // only one entry - $('#selectTarget select').append(''); - } - }, - - // show info for a file - showFile: function ( ed, file ) { - let url = 'projects.html?ed=' + ed + '&file=' + file; - this.displayRight(url); + getPaths: function ( ) { + $('#selectTarget select').append(''); + $('#selectTarget select').append(""); + $('#selectTarget select').append(''); }, // execute a job and show results @@ -95,9 +80,14 @@ const wdbAdmin = { wdbAdmin.uploadFiles(contents); }, + + successfulUL: 0, + failedUL: 0, + numFiles: 0, uploadFiles: function ( collectionContent ) { - $('p img').show(); + $('main p').html(''); + this.numFiles = this.files.length; for (let i = 0; i < this.files.length; i++) { let reader = new FileReader(), @@ -185,7 +175,6 @@ const wdbAdmin = { reader.readAsText(file, "UTF-8"); } - $('p img').hide(); }, doUpload: async function (method, url, headers, formdata, item) { @@ -198,24 +187,28 @@ const wdbAdmin = { processData: false, dataType: "text", success: function (response, textStatus) { + $('#d').html(++wdbAdmin.successfulUL + " erfolgreich, " + wdbAdmin.failedUL + " fehlgeschlagen von insgesamt " + wdbAdmin.numFiles + " Dateien"); wdb.report("success", "uploaded to " + url, textStatus, item); }, error: function (response) { + $('#d').html(wdbAdmin.successfulUL + " erfolgreich, " + ++wdbAdmin.failedUL + " fehlgeschlagen von insgesamt " + wdbAdmin.numFiles + " Dateien"); wdb.report("error", "Error uploading to " + url + " : " + response.status, response.responseText, item); } }); }, files: {}, - setFiles: function ( fileList ) { + setFiles: function ( /** @type { FileList } */ fileList ) { this.files = fileList; $('#results').children().remove(); $('#results').append("Local fileTarget pathStatus"); - for (let file of fileList) { - let task = $('#selectTask input:checked').attr("id"), - filePath = task == "fi" ? file.name : file.webkitRelativePath, - targetPath = $('pre').text() + "/" + $('select').val() + "/" + filePath; + + for ( let file of fileList ) { + let task = $('#selectTask input:checked').attr("id") + , filePath = file.webkitRelativePath === '' ? file.name : file.webkitRelativePath + , delim = $('pre').text().endsWith('/') ? '' : '/' + , targetPath = $('pre').text() + delim + $('select').val() + "/" + filePath; $('#results').append("" + filePath + "" + targetPath + ""); } @@ -233,6 +226,35 @@ $(document).on("change", "select[name=target]", () => { wdbAdmin.setFiles($('#picker')[0].files); }); +$(document).on("submit", "#newProjectForm", ( event ) => { + event.preventDefault(); + /* TODO adjust for RESTv2 meta */ + let rest = window.location.pathname.substring(0, window.location.pathname.indexOf('admin')) + "api/v2/" + , baseUrl = rest + "projects/" + wdb.meta.ed + "/subprojects/" + , newCollectionData = { "title": $('#pName').val(), "short": $('#pShort').val(), "collection": $('#pColl').val() } + , method = $('#pID').val() == '' ? "post" : "put"; + + $.ajax({ + method: method, + url: baseUrl + $('#pID').val(), + contentType: "application/json", + data: JSON.stringify(newCollectionData), + success: function ( data ) { + let url = new URL(window.location.href); + url.searchParams.delete("ed"); + url.searchParams.append("pName", $('#pName').val()?.toString() ?? 'unknown'); + url.searchParams.append("pShort", $('#pShort').val()?.toString() ?? 'unknown'); + url.searchParams.append("pID", $('#pID').val()?.toString() ?? 'unknown'); + url.searchParams.append("collection", data); + url.searchParams.append("ed", $('#pID').val()?.toString() ?? 'unknown'); + window.location.href = url.toString(); + }, + error: function ( data ) { + $('#container').html("

" + data.responseText + "

"); + } + }); +}); + // limit the number of concurrent PUT/POST requests to avoid lockups in eXist let uploadManager = (function() { const MAX_REQUESTS = 1; // local test: produces Jetty errors (“blocking message ...”) for 2 or more... @@ -281,20 +303,9 @@ $(function() { if ( filename === "directoryForm.html" && wdb.meta.ed !== "" ) { let delim = wdb.meta.rest.substr(wdb.meta.rest.length - 1) === '/' ? "" : "/" , url = wdb.meta.rest + delim + "collection/" + wdb.meta.ed + "/structure.json"; - $.ajax({ - method: "get", - url: url, - success: function ( data ) { - let key = Object.keys(data)[0]; - $('#selectTarget pre').first().text(key); - wdbAdmin.getPaths(data[key]); - $("input[type='submit']").prop("disabled", false); - }, - error: function ( response ) { - wdb.report("error", "When trying to create upload form for project " + wdb.parameters.ed + ": ", - response.responseText, $('aside')); - } - }); + wdbAdmin.getPaths(); + $('pre').text(wdb.meta.path); + $('#selectTarget').show(); // dirupload() is called by the form’s formaction handler diff --git a/edoc/resources/scripts/annotate.js b/edoc/resources/js/annotate.js similarity index 100% rename from edoc/resources/scripts/annotate.js rename to edoc/resources/js/annotate.js diff --git a/edoc/resources/scripts/function.js b/edoc/resources/js/function.js similarity index 95% rename from edoc/resources/scripts/function.js rename to edoc/resources/js/function.js index e2d64ba6..23a09df1 100644 --- a/edoc/resources/scripts/function.js +++ b/edoc/resources/js/function.js @@ -41,6 +41,7 @@ const wdb = (function() { }; /* Login and logout */ + /* TODO: this needs to be reworked completely */ let login = function ( event, reload ) { event.preventDefault(); @@ -48,15 +49,18 @@ const wdb = (function() { , password = $('#password').val(); wdb.report("info", "login request"); Cookies.remove('wdbplus'); + + let formdata = new FormData(); + formdata.append("user", username); + formdata.append("password", password); $.ajax({ - url: 'login', + url: '../api/v2/login', method: 'post', - data: { - user: username, - password: password, - edition: $('#edition').val() - }, + data: formdata, + processData: false, + contentType: false, + cache: false, success: function (data) { try { Cookies.set('wdbplus', btoa(username + ':' + password)); @@ -249,31 +253,36 @@ const wdbDocument = { }, /* actual positioning */ - marginaliaPositioningCallback: function (index, element) { - let referenceElementID = $(element).attr('id'), - referenceElementTop = $(element).position().top, - marginNote = $("#margin-" + referenceElementID), - previousMarginNote = marginNote.prev(), - targetTop; - - if (previousMarginNote.length == 0) { - targetTop = referenceElementTop; - } else { - let previousNoteHeight = $(previousMarginNote).height(), - previousNoteTop = $(previousMarginNote).position().top, - minimumTargetTop = previousNoteHeight + previousNoteTop; - - if ( Math.floor(referenceElementTop) < minimumTargetTop ) { - targetTop = previousNoteTop + previousNoteHeight; - } else { + marginaliaPositioningCallback: function ( index, element ) { + let referenceElementID = $(element).attr('id') + , marginNote = $("#margin-" + referenceElementID) + , previousMarginNote = marginNote.prev(); + + try { + let referenceElementTop = $(element).position().top + , targetTop; + + if ( previousMarginNote.length == 0 ) { targetTop = referenceElementTop; + } else { + let previousNoteHeight = $(previousMarginNote).height() ?? 0 + , previousNoteTop = $(previousMarginNote).position().top + , minimumTargetTop = previousNoteHeight + previousNoteTop; + + if ( Math.floor(referenceElementTop) < minimumTargetTop ) { + targetTop = previousNoteTop + previousNoteHeight; + } else { + targetTop = referenceElementTop; + } } - } - wdb.report("info", "position for " + referenceElementID + ': ' + targetTop); - // offset is relative to the document, so the header has to be substracted if top is set via - // CSS - which is necessary because setting the offset will change position and left - marginNote.css('top', targetTop + "px"); + wdb.report("info", "position for " + referenceElementID + ': ' + targetTop); + // offset is relative to the document, so the header has to be substracted if top is set via + // CSS - which is necessary because setting the offset will change position and left + marginNote.css('top', targetTop + "px"); + } catch ( e ) { + wdb.report("error", "Error positioning margin note #" + index + " for " + referenceElementID, e); + } }, /* load an element by ID and display it to the right */ diff --git a/edoc/resources/js/jquery-4.0.0.min.js b/edoc/resources/js/jquery-4.0.0.min.js new file mode 100644 index 00000000..3b89a1ca --- /dev/null +++ b/edoc/resources/js/jquery-4.0.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v4.0.0 | (c) OpenJS Foundation and other contributors | jquery.com/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=t(e,!0):t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";if(!e.document)throw Error("jQuery requires a window with a document");var n=[],r=Object.getPrototypeOf,i=n.slice,o=n.flat?function(e){return n.flat.call(e)}:function(e){return n.concat.apply([],e)},a=n.push,s=n.indexOf,u={},l=u.toString,c=u.hasOwnProperty,f=c.toString,p=f.call(Object),d={};function h(e){return null==e?e+"":"object"==typeof e?u[l.call(e)]||"object":typeof e}function g(e){return null!=e&&e===e.window}function v(e){var t=!!e&&e.length,n=h(e);return!("function"==typeof e||g(e))&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}var y=e.document,m={type:!0,src:!0,nonce:!0,noModule:!0};function x(e,t,n){var r,i=(n=n||y).createElement("script");for(r in i.text=e,m)t&&t[r]&&(i[r]=t[r]);n.head.appendChild(i).parentNode&&i.parentNode.removeChild(i)}var b="4.0.0",w=/HTML$/i,T=function(e,t){return new T.fn.init(e,t)};function C(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}T.fn=T.prototype={jquery:b,constructor:T,length:0,toArray:function(){return i.call(this)},get:function(e){return null==e?i.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=T.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return T.each(this,e)},map:function(e){return this.pushStack(T.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(i.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(T.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(T.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(n>=0&&n+~]|"+E+")"+E+"*"),q=RegExp(E+"|>"),O=/[+~]/,L=y.documentElement,H=L.matches||L.msMatchesSelector;function P(){var e=[];function t(n,r){return e.push(n+" ")>T.expr.cacheLength&&delete t[e.shift()],t[n+" "]=r}return t}function R(e){return e&&void 0!==e.getElementsByTagName&&e}var M="\\["+E+"*("+A+")(?:"+E+"*([*^$|!~]?=)"+E+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+A+"))|)"+E+"*\\]",W=":("+A+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",$={ID:RegExp("^#("+A+")"),CLASS:RegExp("^\\.("+A+")"),TAG:RegExp("^("+A+"|[*])"),ATTR:RegExp("^"+M),PSEUDO:RegExp("^"+W),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i")},I=new RegExp(W),F=RegExp("\\\\[\\da-fA-F]{1,6}"+E+"?|\\\\([^\\r\\n\\f])","g"),B=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))};function _(e){return e.replace(F,B)}function U(e){T.error("Syntax error, unrecognized expression: "+e)}var X=RegExp("^"+E+"*,"+E+"*"),z=P();function Y(e,t){var n,r,i,o,a,s,u,l=z[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=T.expr.preFilter;while(a){for(o in(!n||(r=X.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=N.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(D," ")}),a=a.slice(n.length)),$)(r=T.expr.match[o].exec(a))&&(!u[o]||(r=u[o](r)))&&(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?U(e):z(e,s).slice(0)}function G(e){for(var t=0,n=e.length,r="";t1)},removeAttr:function(e){return this.each(function(){T.removeAttr(this,e)})}}),T.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===e.getAttribute?T.prop(e,t,n):(1===o&&T.isXMLDoc(e)||(i=T.attrHooks[t.toLowerCase()]),void 0!==n)?null===n||!1===n&&0!==t.toLowerCase().indexOf("aria-")?void T.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=e.getAttribute(t))?void 0:r},attrHooks:{},removeAttr:function(e,t){var n,r=0,i=t&&t.match(Q);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),k&&(T.attrHooks.type={set:function(e,t){if("radio"===t&&C(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}});var J=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;function K(e,t){return t?"\0"===e?"\uFFFD":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}T.escapeSelector=function(e){return(e+"").replace(J,K)};var Z=n.sort,ee=n.splice;function et(e,t){if(e===t)return en=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)?e==y||e.ownerDocument==y&&T.contains(y,e)?-1:t==y||t.ownerDocument==y&&T.contains(y,t)?1:0:4&n?-1:1}T.uniqueSort=function(e){var t,n=[],r=0,i=0;if(en=!1,Z.call(e,et),en){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)ee.call(e,n[r],1)}return e},T.fn.uniqueSort=function(){return this.pushStack(T.uniqueSort(i.apply(this)))};var en,er,ei,eo,ea,es,eu=0,el=0,ec=P(),ef=P(),ep=P(),ed=RegExp(E+"+","g"),eh=RegExp("^"+A+"$"),eg=T.extend({needsContext:RegExp("^"+E+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)","i")},$),ev=/^(?:input|select|textarea|button)$/i,ey=/^h\d$/i,em=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ex=function(){eE()},eb=eS(function(e){return!0===e.disabled&&C(e,"fieldset")},{dir:"parentNode",next:"legend"});function ew(e,t,n,r){var i,o,s,u,l,c,f,p=t&&t.ownerDocument,d=t?t.nodeType:9;if(n=n||[],"string"!=typeof e||!e||1!==d&&9!==d&&11!==d)return n;if(!r&&(eE(t),t=t||eo,es)){if(11!==d&&(l=em.exec(e))){if(i=l[1]){if(9===d)return(s=t.getElementById(i))&&a.call(n,s),n;else if(p&&(s=p.getElementById(i))&&T.contains(t,s))return a.call(n,s),n}else if(l[2])return a.apply(n,t.getElementsByTagName(e)),n;else if((i=l[3])&&t.getElementsByClassName)return a.apply(n,t.getElementsByClassName(i)),n}if(!ep[e+" "]&&(!S||!S.test(e))){if(f=e,p=t,1===d&&(q.test(e)||N.test(e))){((p=O.test(e)&&R(t.parentNode)||t)!=t||k)&&((u=t.getAttribute("id"))?u=T.escapeSelector(u):t.setAttribute("id",u=T.expando)),o=(c=Y(e)).length;while(o--)c[o]=(u?"#"+u:":scope")+" "+G(c[o]);f=c.join(",")}try{return a.apply(n,p.querySelectorAll(f)),n}catch(t){ep(e,!0)}finally{u===T.expando&&t.removeAttribute("id")}}}return eq(e.replace(D,"$1"),t,n,r)}function eT(e){return e[T.expando]=!0,e}function eC(e){return function(t){if("form"in t){if(t.parentNode&&!1===t.disabled){if("label"in t)if("label"in t.parentNode)return t.parentNode.disabled===e;else return t.disabled===e;return t.isDisabled===e||!e!==t.isDisabled&&eb(t)===e}return t.disabled===e}return"label"in t&&t.disabled===e}}function ej(e){return eT(function(t){return t*=1,eT(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function eE(e){var t,n=e?e.ownerDocument||e:y;n!=eo&&9===n.nodeType&&(ea=(eo=n).documentElement,es=!T.isXMLDoc(eo),k&&y!=eo&&(t=eo.defaultView)&&t.top!==t&&t.addEventListener("unload",ex))}for(er in ew.matches=function(e,t){return ew(e,null,null,t)},ew.matchesSelector=function(e,t){if(eE(e),es&&!ep[t+" "]&&(!S||!S.test(t)))try{return H.call(e,t)}catch(e){ep(t,!0)}return ew(t,eo,null,[e]).length>0},T.expr={cacheLength:50,createPseudo:eT,match:eg,find:{ID:function(e,t){if(void 0!==t.getElementById&&es){var n=t.getElementById(e);return n?[n]:[]}},TAG:function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},CLASS:function(e,t){if(void 0!==t.getElementsByClassName&&es)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=_(e[1]),e[3]=_(e[3]||e[4]||e[5]||""),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||U(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&U(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return $.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&I.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{ID:function(e){var t=_(e);return function(e){return e.getAttribute("id")===t}},TAG:function(e){var t=_(e).toLowerCase();return"*"===e?function(){return!0}:function(e){return C(e,t)}},CLASS:function(e){var t=ec[e+" "];return t||(t=RegExp("(^|"+E+")"+e+"("+E+"|$)"))&&ec(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=T.attr(r,e);return null==i?"!="===t:!t||((i+="","="===t)?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace(ed," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h=o!==a?"nextSibling":"previousSibling",g=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!u&&!s,m=!1;if(g){if(o){while(h){f=t;while(f=f[h])if(s?C(f,v):1===f.nodeType)return!1;d=h="only"===e&&!d&&"nextSibling"}return!0}if(d=[a?g.firstChild:g.lastChild],a&&y){m=(p=(l=(c=g[T.expando]||(g[T.expando]={}))[e]||[])[0]===eu&&l[1])&&l[2],f=p&&g.childNodes[p];while(f=++p&&f&&f[h]||(m=p=0)||d.pop())if(1===f.nodeType&&++m&&f===t){c[e]=[eu,p,m];break}}else if(y&&(m=p=(l=(c=t[T.expando]||(t[T.expando]={}))[e]||[])[0]===eu&&l[1]),!1===m){while(f=++p&&f&&f[h]||(m=p=0)||d.pop())if((s?C(f,v):1===f.nodeType)&&++m&&(y&&((c=f[T.expando]||(f[T.expando]={}))[e]=[eu,m]),f===t))break}return(m-=i)===r||m%r==0&&m/r>=0}}},PSEUDO:function(e,t){var n=T.expr.pseudos[e]||T.expr.setFilters[e.toLowerCase()]||U("unsupported pseudo: "+e);return n[T.expando]?n(t):n}},pseudos:{not:eT(function(e){var t=[],n=[],r=eN(e.replace(D,"$1"));return r[T.expando]?eT(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:eT(function(e){return function(t){return ew(e,t).length>0}}),contains:eT(function(e){return e=_(e),function(t){return(t.textContent||T.text(t)).indexOf(e)>-1}}),lang:eT(function(e){return eh.test(e||"")||U("unsupported lang: "+e),e=_(e).toLowerCase(),function(t){var n;do if(n=es?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===ea},focus:function(e){return e===eo.activeElement&&eo.hasFocus()&&!!(e.type||e.href||~e.tabIndex)},enabled:eC(!1),disabled:eC(!0),checked:function(e){return C(e,"input")&&!!e.checked||C(e,"option")&&!!e.selected},selected:function(e){return k&&e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!T.expr.pseudos.empty(e)},header:function(e){return ey.test(e.nodeName)},input:function(e){return ev.test(e.nodeName)},button:function(e){return C(e,"input")&&"button"===e.type||C(e,"button")},text:function(e){return C(e,"input")&&"text"===e.type},first:ej(function(){return[0]}),last:ej(function(e,t){return[t-1]}),eq:ej(function(e,t,n){return[n<0?n+t:n]}),even:ej(function(e,t){for(var n=0;nt?t:n;--r>=0;)e.push(r);return e}),gt:ej(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function eA(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s-1},l,!0),d=[function(e,t,r){var i=!u&&(r||t!=ei)||((n=t).nodeType?f(e,t,r):p(e,t,r));return n=null,i}];c-1&&(e[f]=!(u[f]=d))}}else h=eA(h===u?h.splice(y,h.length):h),o?o(null,u,h,c):a.apply(u,h)})}(c>1&&eD(d),c>1&&G(t.slice(0,c-1).concat({value:" "===t[c-2].type?"*":""})).replace(D,"$1"),r,c0,r=l.length>0,i=function(e,t,i,o,s){var c,f,p,d=0,h="0",g=e&&[],v=[],y=ei,m=e||r&&T.expr.find.TAG("*",s),x=eu+=null==y?1:Math.random()||.1;for(s&&(ei=t==eo||t||s);null!=(c=m[h]);h++){if(r&&c){f=0,t||c.ownerDocument==eo||(eE(c),i=!es);while(p=l[f++])if(p(c,t||eo,i)){a.call(o,c);break}s&&(eu=x)}n&&((c=!p&&c)&&d--,e&&g.push(c))}if(d+=h,n&&h!==d){f=0;while(p=u[f++])p(g,v,t,i);if(e){if(d>0)while(h--)g[h]||v[h]||(v[h]=j.call(o));v=eA(v)}a.apply(o,v),s&&!e&&v.length>0&&d+u.length>1&&T.uniqueSort(o)}return s&&(eu=x,ei=y),g},n?eT(i):i))).selector=e}return c}function eq(e,t,n,r){var i,o,s,u,l,c="function"==typeof e&&e,f=!r&&Y(e=c.selector||e);if(n=n||[],1===f.length){if((o=f[0]=f[0].slice(0)).length>2&&"ID"===(s=o[0]).type&&9===t.nodeType&&es&&T.expr.relative[o[1].type]){if(!(t=(T.expr.find.ID(_(s.matches[0]),t)||[])[0]))return n;c&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=eg.needsContext.test(e)?0:o.length;while(i--){if(s=o[i],T.expr.relative[u=s.type])break;if((l=T.expr.find[u])&&(r=l(_(s.matches[0]),O.test(o[0].type)&&R(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&G(o)))return a.apply(n,r),n;break}}}return(c||eN(e,f))(r,t,!es,n,!t||O.test(e)&&R(t.parentNode)||t),n}function eO(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&T(e).is(n))break;r.push(e)}return r}function eL(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}ek.prototype=T.expr.pseudos,T.expr.setFilters=new ek,eE(),T.find=ew,ew.compile=eN,ew.select=eq,ew.setDocument=eE,ew.tokenize=Y;var eH=T.expr.match.needsContext,eP=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function eR(e){return"<"===e[0]&&">"===e[e.length-1]&&e.length>=3}function eM(e,t,n){return"function"==typeof t?T.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?T.grep(e,function(e){return e===t!==n}):"string"!=typeof t?T.grep(e,function(e){return s.call(t,e)>-1!==n}):T.filter(t,e,n)}T.filter=function(e,t,n){var r=t[0];return(n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType)?T.find.matchesSelector(r,e)?[r]:[]:T.find.matches(e,T.grep(t,function(e){return 1===e.nodeType}))},T.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(T(e).filter(function(){for(t=0;t1?T.uniqueSort(n):n},filter:function(e){return this.pushStack(eM(this,e||[],!1))},not:function(e){return this.pushStack(eM(this,e||[],!0))},is:function(e){return!!eM(this,"string"==typeof e&&eH.test(e)?T(e):e||[],!1).length}});var eW,e$=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(T.fn.init=function(e,t){var n,r;if(!e)return this;if(e.nodeType)return this[0]=e,this.length=1,this;if("function"==typeof e)return void 0!==eW.ready?eW.ready(e):e(T);if(eR(n=e+""))n=[null,e,null];else{if("string"!=typeof e)return T.makeArray(e,this);n=e$.exec(e)}if(n&&(n[1]||!t))if(!n[1])return(r=y.getElementById(n[2]))&&(this[0]=r,this.length=1),this;else{if(t=t instanceof T?t[0]:t,T.merge(this,T.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:y,!0)),eP.test(n[1])&&T.isPlainObject(t))for(n in t)"function"==typeof this[n]?this[n](t[n]):this.attr(n,t[n]);return this}return!t||t.jquery?(t||eW).find(e):this.constructor(t).find(e)}).prototype=T.fn,eW=T(y);var eI=/^(?:parents|prev(?:Until|All))/,eF={children:!0,contents:!0,next:!0,prev:!0};function eB(e,t){while((e=e[t])&&1!==e.nodeType);return e}function e_(e){return e}function eU(e){throw e}function eX(e,t,n,r){var i;try{e&&"function"==typeof(i=e.promise)?i.call(e).done(t).fail(n):e&&"function"==typeof(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n(e)}}T.fn.extend({has:function(e){var t=T(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&T.find.matchesSelector(n,e))){o.push(n);break}}return this.pushStack(o.length>1?T.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?s.call(T(e),this[0]):s.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(T.uniqueSort(T.merge(this.get(),T(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),T.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return eO(e,"parentNode")},parentsUntil:function(e,t,n){return eO(e,"parentNode",n)},next:function(e){return eB(e,"nextSibling")},prev:function(e){return eB(e,"previousSibling")},nextAll:function(e){return eO(e,"nextSibling")},prevAll:function(e){return eO(e,"previousSibling")},nextUntil:function(e,t,n){return eO(e,"nextSibling",n)},prevUntil:function(e,t,n){return eO(e,"previousSibling",n)},siblings:function(e){return eL((e.parentNode||{}).firstChild,e)},children:function(e){return eL(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(C(e,"template")&&(e=e.content||e),T.merge([],e.childNodes))}},function(e,t){T.fn[e]=function(n,r){var i=T.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=T.filter(r,i)),this.length>1&&(eF[e]||T.uniqueSort(i),eI.test(e)&&i.reverse()),this.pushStack(i)}}),T.Callbacks=function(e){e="string"==typeof e?(t=e,n={},T.each(t.match(Q)||[],function(e,t){n[t]=!0}),n):T.extend({},e);var t,n,r,i,o,a,s=[],u=[],l=-1,c=function(){for(a=a||e.once,o=r=!0;u.length;l=-1){i=u.shift();while(++l-1)s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?T.inArray(e,s)>-1:s.length>0},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=i="",this},disabled:function(){return!s},lock:function(){return a=u=[],i||r||(s=i=""),this},locked:function(){return!!a},fireWith:function(e,t){return!a&&(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),r||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},T.extend({Deferred:function(t){var n=[["notify","progress",T.Callbacks("memory"),T.Callbacks("memory"),2],["resolve","done",T.Callbacks("once memory"),T.Callbacks("once memory"),0,"resolved"],["reject","fail",T.Callbacks("once memory"),T.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(e){return i.then(null,e)},pipe:function(){var e=arguments;return T.Deferred(function(t){T.each(n,function(n,r){var i="function"==typeof e[r[4]]&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){var o=0;function a(t,n,r,i){return function(){var s=this,u=arguments,l=function(){var e,l;if(!(t=o&&(r!==eU&&(s=void 0,u=[e]),n.rejectWith(s,u))}};t?c():(T.Deferred.getErrorHook&&(c.error=T.Deferred.getErrorHook()),e.setTimeout(c))}}return T.Deferred(function(e){n[0][3].add(a(0,e,"function"==typeof i?i:e_,e.notifyWith)),n[1][3].add(a(0,e,"function"==typeof t?t:e_)),n[2][3].add(a(0,e,"function"==typeof r?r:eU))}).promise()},promise:function(e){return null!=e?T.extend(e,i):i}},o={};return T.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[3-e][3].disable,n[0][2].lock,n[0][3].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),o=i.call(arguments),a=T.Deferred(),s=function(e){return function(n){r[e]=this,o[e]=arguments.length>1?i.call(arguments):n,--t||a.resolveWith(r,o)}};if(t<=1&&(eX(e,a.done(s(n)).resolve,a.reject,!t),"pending"===a.state()||"function"==typeof(o[n]&&o[n].then)))return a.then();while(n--)eX(o[n],s(n),a.reject);return a.promise()}});var ez=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;T.Deferred.exceptionHook=function(t,n){t&&ez.test(t.name)&&e.console.warn("jQuery.Deferred exception",t,n)},T.readyException=function(t){e.setTimeout(function(){throw t})};var eY=T.Deferred();function eG(){y.removeEventListener("DOMContentLoaded",eG),e.removeEventListener("load",eG),T.ready()}T.fn.ready=function(e){return eY.then(e).catch(function(e){T.readyException(e)}),this},T.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--T.readyWait:T.isReady)||(T.isReady=!0,!0!==e&&--T.readyWait>0||eY.resolveWith(y,[T]))}}),T.ready.then=eY.then,"loading"!==y.readyState?e.setTimeout(T.ready):(y.addEventListener("DOMContentLoaded",eG),e.addEventListener("load",eG));var eV=/-([a-z])/g;function eQ(e,t){return t.toUpperCase()}function eJ(e){return e.replace(eV,eQ)}function eK(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType}function eZ(){this.expando=T.expando+eZ.uid++}eZ.uid=1,eZ.prototype={cache:function(e){var t=e[this.expando];return!t&&(t=Object.create(null),eK(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[eJ(t)]=n;else for(r in t)i[eJ(r)]=t[r];return n},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][eJ(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(eJ):(t=eJ(t))in r?[t]:t.match(Q)||[]).length;while(n--)delete r[t[n]]}(void 0===t||T.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!T.isEmptyObject(t)}};var e0=new eZ,e1=new eZ,e2=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,e3=/[A-Z]/g;function e4(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(e3,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{i=n,n="true"===i||"false"!==i&&("null"===i?null:i===+i+""?+i:e2.test(i)?JSON.parse(i):i)}catch(e){}e1.set(e,t,n)}else n=void 0;return n}T.extend({hasData:function(e){return e1.hasData(e)||e0.hasData(e)},data:function(e,t,n){return e1.access(e,t,n)},removeData:function(e,t){e1.remove(e,t)},_data:function(e,t,n){return e0.access(e,t,n)},_removeData:function(e,t){e0.remove(e,t)}}),T.fn.extend({data:function(e,t){var n,r,i,o=this[0],a=o&&o.attributes;if(void 0===e){if(this.length&&(i=e1.get(o),1===o.nodeType&&!e0.get(o,"hasDataAttrs"))){n=a.length;while(n--)a[n]&&0===(r=a[n].name).indexOf("data-")&&e4(o,r=eJ(r.slice(5)),i[r]);e0.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof e?this.each(function(){e1.set(this,e)}):V(this,function(t){var n;if(o&&void 0===t)return void 0!==(n=e1.get(o,e))||void 0!==(n=e4(o,e))?n:void 0;this.each(function(){e1.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){e1.remove(this,e)})}}),T.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=e0.get(e,t),n&&(!r||Array.isArray(n)?r=e0.set(e,t,T.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=T.queue(e,t),r=n.length,i=n.shift(),o=T._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){T.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return e0.get(e,n)||e0.set(e,n,{empty:T.Callbacks("once memory").add(function(){e0.remove(e,[t+"queue",n])})})}}),T.fn.extend({queue:function(e,t){var n=2;return("string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]*)/i,tc={thead:["table"],col:["colgroup","table"],tr:["tbody","table"],td:["tr","tbody","table"]};function tf(e,t){var r;return(r=void 0!==e.getElementsByTagName?n.slice.call(e.getElementsByTagName(t||"*")):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&C(e,t))?T.merge([e],r):r}tc.tbody=tc.tfoot=tc.colgroup=tc.caption=tc.thead,tc.th=tc.td;var tp=/^$|^module$|\/(?:java|ecma)script/i;function td(e,t){for(var n=0,r=e.length;n-1)s=s.appendChild(t.createElement(u[c]));s.innerHTML=T.htmlPrefilter(a),T.merge(p,s.childNodes),(s=f.firstChild).textContent=""}else p.push(t.createTextNode(a));f.textContent="",d=0;while(a=p[d++]){if(i&&T.inArray(a,i)>-1){o&&o.push(a);continue}if(l=ts(a),s=tf(f.appendChild(a),"script"),l&&td(s),r){c=0;while(a=s[c++])tp.test(a.type||"")&&r.push(a)}}return f}function tv(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ty(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function tm(e,t,n,r){t=o(t);var i,a,s,u,l,c,f=0,p=e.length,d=p-1,h=t[0];if("function"==typeof h)return e.each(function(i){var o=e.eq(i);t[0]=h.call(this,i,o.html()),tm(o,t,n,r)});if(p&&(a=(i=tg(t,e[0].ownerDocument,!1,e,r)).firstChild,1===i.childNodes.length&&(i=a),a||r)){for(u=(s=T.map(tf(i,"script"),tv)).length;f=1)){for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(n=0,o=[],a={};n-1:T.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}}return l=this,u0&&td(a,!u&&tf(e,"script")),s},cleanData:function(e){for(var t,n,r,i=T.event.special,o=0;void 0!==(n=e[o]);o++)if(eK(n)){if(t=n[e0.expando]){if(t.events)for(r in t.events)i[r]?T.event.remove(n,r):T.removeEvent(n,r,t.handle);n[e0.expando]=void 0}n[e1.expando]&&(n[e1.expando]=void 0)}}}),T.fn.extend({detach:function(e){return tD(this,e,!0)},remove:function(e){return tD(this,e)},text:function(e){return V(this,function(e){return void 0===e?T.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=e)})},null,e,arguments.length)},append:function(){return tm(this,arguments,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&tk(this,e).appendChild(e)})},prepend:function(){return tm(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=tk(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return tm(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return tm(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(T.cleanData(tf(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return T.clone(this,e,t)})},html:function(e){return V(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!tE.test(e)&&!tc[(tl.exec(e)||["",""])[1].toLowerCase()]){e=T.htmlPrefilter(e);try{for(;nT.inArray(this,e)&&(T.cleanData(tf(this)),n&&n.replaceChild(t,this))},e)}}),T.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){T.fn[e]=function(e){for(var n,r=[],i=T(e),o=i.length-1,s=0;s<=o;s++)n=s===o?this:this.clone(!0),T(i[s])[t](n),a.apply(r,n);return this.pushStack(r)}});var tA=RegExp("^("+e5+")(?!px)[a-z%]+$","i"),tN=/^--/;function tq(t){var n=t.ownerDocument.defaultView;return n||(n=e),n.getComputedStyle(t)}function tO(e,t,n){var r,i=tN.test(t);return(n=n||tq(e))&&(r=n.getPropertyValue(t)||n[t],i&&r&&(r=r.replace(D,"$1")||void 0),""!==r||ts(e)||(r=T.style(e,t))),void 0!==r?r+"":r}var tL=["Webkit","Moz","ms"],tH=y.createElement("div").style;function tP(e){return e in tH?e:function(e){var t=e[0].toUpperCase()+e.slice(1),n=tL.length;while(n--)if((e=tL[n]+t)in tH)return e}(e)||e}var tR,tM,tW=y.createElement("table");function t$(){if(tW&&tW.style){var t,n=y.createElement("col"),r=y.createElement("tr"),i=y.createElement("td");if(tW.style.cssText="position:absolute;left:-11111px;border-collapse:separate;border-spacing:0",r.style.cssText="box-sizing:content-box;border:1px solid;height:1px",i.style.cssText="height:9px;width:9px;padding:0",n.span=2,L.appendChild(tW).appendChild(n).parentNode.appendChild(r).appendChild(i).parentNode.appendChild(i.cloneNode(!0)),0===tW.offsetWidth)return void L.removeChild(tW);t=e.getComputedStyle(r),tM=k||18===Math.round(parseFloat(e.getComputedStyle(n).width)),tR=Math.round(parseFloat(t.height)+parseFloat(t.borderTopWidth)+parseFloat(t.borderBottomWidth))===r.offsetHeight,L.removeChild(tW),tW=null}}T.extend(d,{reliableTrDimensions:function(){return t$(),tR},reliableColDimensions:function(){return t$(),tM}});var tI={position:"absolute",visibility:"hidden",display:"block"},tF={letterSpacing:"0",fontWeight:"400"};function tB(e,t,n){var r=e9.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function t_(e,t,n,r,i,o){var a=+("width"===t),s=0,u=0,l=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(l+=T.css(e,n+e6[a],!0,i)),r?("content"===n&&(u-=T.css(e,"padding"+e6[a],!0,i)),"margin"!==n&&(u-=T.css(e,"border"+e6[a]+"Width",!0,i))):(u+=T.css(e,"padding"+e6[a],!0,i),"padding"!==n?u+=T.css(e,"border"+e6[a]+"Width",!0,i):s+=T.css(e,"border"+e6[a]+"Width",!0,i));return!r&&o>=0&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u+l}function tU(e,t,n){var r=tq(e),i=(k||n)&&"border-box"===T.css(e,"boxSizing",!1,r),o=i,a=tO(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(tA.test(a)){if(!n)return a;a="auto"}return("auto"===a||k&&i||!d.reliableColDimensions()&&C(e,"col")||!d.reliableTrDimensions()&&C(e,"tr"))&&e.getClientRects().length&&(i="border-box"===T.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+t_(e,t,n||(i?"border":"content"),o,r,a)+"px"}function tX(e,t,n,r,i){return new tX.prototype.init(e,t,n,r,i)}T.extend({cssHooks:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=ti(t),u=tN.test(t),l=e.style;if(u||(t=tP(s)),a=T.cssHooks[t]||T.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];if("string"==(o=typeof n)&&(i=e9.exec(n))&&i[1]&&(n=tn(e,t,i),o="number"),null!=n&&n==n)"number"===o&&(n+=i&&i[3]||(tt(s)?"px":"")),k&&""===n&&0===t.indexOf("background")&&(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n)}},css:function(e,t,n,r){var i,o,a,s=ti(t);return(tN.test(t)||(t=tP(s)),(a=T.cssHooks[t]||T.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=tO(e,t,r)),"normal"===i&&t in tF&&(i=tF[t]),""===n||n)?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),T.each(["height","width"],function(e,t){T.cssHooks[t]={get:function(e,n,r){if(n)return"none"===T.css(e,"display")?function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r}(e,tI,function(){return tU(e,t,r)}):tU(e,t,r)},set:function(e,n,r){var i,o=tq(e),a=r&&"border-box"===T.css(e,"boxSizing",!1,o),s=r?t_(e,t,r,a,o):0;return s&&(i=e9.exec(n))&&"px"!==(i[3]||"px")&&(e.style[t]=n,n=T.css(e,t)),tB(e,n,s)}}}),T.each({margin:"",padding:"",border:"Width"},function(e,t){T.cssHooks[e+t]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[e+e6[r]+t]=o[r]||o[r-2]||o[0];return i}},"margin"!==e&&(T.cssHooks[e+t].set=tB)}),T.fn.extend({css:function(e,t){return V(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=tq(e),i=t.length;a1)}}),T.Tween=tX,tX.prototype={constructor:tX,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||T.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(tt(n)?"px":"")},cur:function(){var e=tX.propHooks[this.prop];return e&&e.get?e.get(this):tX.propHooks._default.get(this)},run:function(e){var t,n=tX.propHooks[this.prop];return this.options.duration?this.pos=t=T.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):tX.propHooks._default.set(this),this}},tX.prototype.init.prototype=tX.prototype,tX.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=T.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){T.fx.step[e.prop]?T.fx.step[e.prop](e):1===e.elem.nodeType&&(T.cssHooks[e.prop]||null!=e.elem.style[tP(e.prop)])?T.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},T.easing={linear:function(e){return e},swing:function(e){return .5-Math.cos(e*Math.PI)/2},_default:"swing"},T.fx=tX.prototype.init,T.fx.step={};var tz,tY,tG=/^(?:toggle|show|hide)$/,tV=/queueHooks$/;function tQ(){return e.setTimeout(function(){tz=void 0}),tz=Date.now()}function tJ(e,t){var n,r=0,i={height:e};for(t=+!!t;r<4;r+=2-t)i["margin"+(n=e6[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function tK(e,t,n){for(var r,i=(tZ.tweeners[t]||[]).concat(tZ.tweeners["*"]),o=0,a=i.length;o1)},removeProp:function(e){return this.each(function(){delete this[T.propFix[e]||e]})}}),T.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return(1===o&&T.isXMLDoc(e)||(t=T.propFix[t]||t,i=T.propHooks[t]),void 0!==n)?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=e.getAttribute("tabindex");return t?parseInt(t,10):t0.test(e.nodeName)||t1.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),k&&(T.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),T.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){T.propFix[this.toLowerCase()]=this}),T.fn.extend({addClass:function(e){var t,n,r,i,o,a;return"function"==typeof e?this.each(function(t){T(this).addClass(e.call(this,t,t3(this)))}):(t=t4(e)).length?this.each(function(){if(r=t3(this),n=1===this.nodeType&&" "+t2(r)+" "){for(o=0;on.indexOf(" "+i+" ")&&(n+=i+" ");r!==(a=t2(n))&&this.setAttribute("class",a)}}):this},removeClass:function(e){var t,n,r,i,o,a;return"function"==typeof e?this.each(function(t){T(this).removeClass(e.call(this,t,t3(this)))}):arguments.length?(t=t4(e)).length?this.each(function(){if(r=t3(this),n=1===this.nodeType&&" "+t2(r)+" "){for(o=0;o-1)n=n.replace(" "+i+" "," ")}r!==(a=t2(n))&&this.setAttribute("class",a)}}):this:this.attr("class","")},toggleClass:function(e,t){var n,r,i,o;return"function"==typeof e?this.each(function(n){T(this).toggleClass(e.call(this,n,t3(this),t),t)}):"boolean"==typeof t?t?this.addClass(e):this.removeClass(e):(n=t4(e)).length?this.each(function(){for(i=0,o=T(this);i-1)return!0;return!1}}),T.fn.extend({val:function(e){var t,n,r,i=this[0];if(!arguments.length)return i?(t=T.valHooks[i.type]||T.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:null==(n=i.value)?"":n:void 0;return r="function"==typeof e,this.each(function(n){var i;1===this.nodeType&&(null==(i=r?e.call(this,n,T(this).val()):e)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=T.map(i,function(e){return null==e?"":e+""})),(t=T.valHooks[this.type]||T.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))})}}),T.extend({valHooks:{select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k&&(T.valHooks.option={get:function(e){var t=e.getAttribute("value");return null!=t?t:t2(T.text(e))}}),T.each(["radio","checkbox"],function(){T.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=T.inArray(T(e).val(),t)>-1}}});var t5=/^(?:focusinfocus|focusoutblur)$/,t9=function(e){e.stopPropagation()};T.extend(T.event,{trigger:function(t,n,r,i){var o,a,s,u,l,f,p,d,h=[r||y],v=c.call(t,"type")?t.type:t,m=c.call(t,"namespace")?t.namespace.split("."):[];if((a=d=s=r=r||y,!(3===r.nodeType||8===r.nodeType||t5.test(v+T.event.triggered)))&&(v.indexOf(".")>-1&&(v=(m=v.split(".")).shift(),m.sort()),l=0>v.indexOf(":")&&"on"+v,(t=t[T.expando]?t:new T.Event(v,"object"==typeof t&&t)).isTrigger=i?2:3,t.namespace=m.join("."),t.rnamespace=t.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:T.makeArray(n,[t]),p=T.event.special[v]||{},i||!p.trigger||!1!==p.trigger.apply(r,n))){if(!i&&!p.noBubble&&!g(r)){for(u=p.delegateType||v,!t5.test(u+v)&&(a=a.parentNode);a;a=a.parentNode)h.push(a),s=a;s===(r.ownerDocument||y)&&h.push(s.defaultView||s.parentWindow||e)}o=0;while((a=h[o++])&&!t.isPropagationStopped())d=a,t.type=o>1?u:p.bindType||v,(f=(e0.get(a,"events")||Object.create(null))[t.type]&&e0.get(a,"handle"))&&f.apply(a,n),(f=l&&a[l])&&f.apply&&eK(a)&&(t.result=f.apply(a,n),!1===t.result&&t.preventDefault());return t.type=v,!i&&!t.isDefaultPrevented()&&(!p._default||!1===p._default.apply(h.pop(),n))&&eK(r)&&l&&"function"==typeof r[v]&&!g(r)&&((s=r[l])&&(r[l]=null),T.event.triggered=v,t.isPropagationStopped()&&d.addEventListener(v,t9),r[v](),t.isPropagationStopped()&&d.removeEventListener(v,t9),T.event.triggered=void 0,s&&(r[l]=s)),t.result}},simulate:function(e,t,n){var r=T.extend(new T.Event,n,{type:e,isSimulated:!0});T.event.trigger(r,null,t)}}),T.fn.extend({trigger:function(e,t){return this.each(function(){T.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return T.event.trigger(e,t,n,!0)}});var t6=e.location,t8={guid:Date.now()},t7=/\?/;T.parseXML=function(t){var n,r;if(!t||"string"!=typeof t)return null;try{n=new e.DOMParser().parseFromString(t,"text/xml")}catch(e){}return r=n&&n.getElementsByTagName("parsererror")[0],(!n||r)&&T.error("Invalid XML: "+(r?T.map(r.childNodes,function(e){return e.textContent}).join("\n"):t)),n};var ne=/\[\]$/,nt=/\r?\n/g,nn=/^(?:submit|button|image|reset|file)$/i,nr=/^(?:input|select|textarea|keygen)/i;T.param=function(e,t){var n,r=[],i=function(e,t){var n="function"==typeof t?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!T.isPlainObject(e))T.each(e,function(){i(this.name,this.value)});else for(n in e)!function e(t,n,r,i){var o;if(Array.isArray(n))T.each(n,function(n,o){r||ne.test(t)?i(t,o):e(t+"["+("object"==typeof o&&null!=o?n:"")+"]",o,r,i)});else if(r||"object"!==h(n))i(t,n);else for(o in n)e(t+"["+o+"]",n[o],r,i)}(n,e[n],t,i);return r.join("&")},T.fn.extend({serialize:function(){return T.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=T.prop(this,"elements");return e?T.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!T(this).is(":disabled")&&nr.test(this.nodeName)&&!nn.test(e)&&(this.checked||!tx.test(e))}).map(function(e,t){var n=T(this).val();return null==n?null:Array.isArray(n)?T.map(n,function(e){return{name:t.name,value:e.replace(nt,"\r\n")}}):{name:t.name,value:n.replace(nt,"\r\n")}}).get()}});var ni=/%20/g,no=/#.*$/,na=/([?&])_=[^&]*/,ns=/^(.*?):[ \t]*([^\r\n]*)$/mg,nu=/^(?:GET|HEAD)$/,nl=/^\/\//,nc={},nf={},np="*/".concat("*"),nd=y.createElement("a");function nh(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(Q)||[];if("function"==typeof n)while(r=o[i++])"+"===r[0]?(e[r=r.slice(1)||"*"]=e[r]||[]).unshift(n):(e[r]=e[r]||[]).push(n)}}function ng(e,t,n,r){var i={},o=e===nf;function a(s){var u;return i[s]=!0,T.each(e[s]||[],function(e,s){var l=s(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):void 0:(t.dataTypes.unshift(l),a(l),!1)}),u}return a(t.dataTypes[0])||!i["*"]&&a("*")}function nv(e,t){var n,r,i=T.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&T.extend(!0,e,r),e}nd.href=t6.href,T.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:t6.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(t6.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":np,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":T.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?nv(nv(e,T.ajaxSettings),t):nv(T.ajaxSettings,e)},ajaxPrefilter:nh(nc),ajaxTransport:nh(nf),ajax:function(t,n){"object"==typeof t&&(n=t,t=void 0),n=n||{};var r,i,o,a,s,u,l,c,f,p,d=T.ajaxSetup({},n),h=d.context||d,g=d.context&&(h.nodeType||h.jquery)?T(h):T.event,v=T.Deferred(),m=T.Callbacks("once memory"),x=d.statusCode||{},b={},w={},C="canceled",j={readyState:0,getResponseHeader:function(e){var t;if(l){if(!a){a={};while(t=ns.exec(o))a[t[1].toLowerCase()+" "]=(a[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=a[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return l?o:null},setRequestHeader:function(e,t){return null==l&&(b[e=w[e.toLowerCase()]=w[e.toLowerCase()]||e]=t),this},overrideMimeType:function(e){return null==l&&(d.mimeType=e),this},statusCode:function(e){var t;if(e)if(l)j.always(e[j.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||C;return r&&r.abort(t),E(0,t),this}};if(v.promise(j),d.url=((t||d.url||t6.href)+"").replace(nl,t6.protocol+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=(d.dataType||"*").toLowerCase().match(Q)||[""],null==d.crossDomain){u=y.createElement("a");try{u.href=d.url,u.href=u.href,d.crossDomain=nd.protocol+"//"+nd.host!=u.protocol+"//"+u.host}catch(e){d.crossDomain=!0}}if(ng(nc,d,n,j),d.data&&d.processData&&"string"!=typeof d.data&&(d.data=T.param(d.data,d.traditional)),l)return j;for(f in(c=T.event&&d.global)&&0==T.active++&&T.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!nu.test(d.type),i=d.url.replace(no,""),d.hasContent?d.data&&d.processData&&0===(d.contentType||"").indexOf("application/x-www-form-urlencoded")&&(d.data=d.data.replace(ni,"+")):(p=d.url.slice(i.length),d.data&&(d.processData||"string"==typeof d.data)&&(i+=(t7.test(i)?"&":"?")+d.data,delete d.data),!1===d.cache&&(i=i.replace(na,"$1"),p=(t7.test(i)?"&":"?")+"_="+t8.guid+++p),d.url=i+p),d.ifModified&&(T.lastModified[i]&&j.setRequestHeader("If-Modified-Since",T.lastModified[i]),T.etag[i]&&j.setRequestHeader("If-None-Match",T.etag[i])),(d.data&&d.hasContent&&!1!==d.contentType||n.contentType)&&j.setRequestHeader("Content-Type",d.contentType),j.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+np+"; q=0.01":""):d.accepts["*"]),d.headers)j.setRequestHeader(f,d.headers[f]);if(d.beforeSend&&(!1===d.beforeSend.call(h,j,d)||l))return j.abort();if(C="abort",m.add(d.complete),j.done(d.success),j.fail(d.error),r=ng(nf,d,n,j)){if(j.readyState=1,c&&g.trigger("ajaxSend",[j,d]),l)return j;d.async&&d.timeout>0&&(s=e.setTimeout(function(){j.abort("timeout")},d.timeout));try{l=!1,r.send(b,E)}catch(e){if(l)throw e;E(-1,e)}}else E(-1,"No Transport");function E(t,n,a,u){var f,p,y,b,w,C=n;!l&&(l=!0,s&&e.clearTimeout(s),r=void 0,o=u||"",j.readyState=4*(t>0),f=t>=200&&t<300||304===t,a&&(b=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r){for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(d,j,a)),!f&&T.inArray("script",d.dataTypes)>-1&&0>T.inArray("json",d.dataTypes)&&(d.converters["text script"]=function(){}),b=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift()){if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o])){for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}}if(!0!==a)if(a&&e.throws)t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}}return{state:"success",data:t}}(d,b,j,f),f?(d.ifModified&&((w=j.getResponseHeader("Last-Modified"))&&(T.lastModified[i]=w),(w=j.getResponseHeader("etag"))&&(T.etag[i]=w)),204===t||"HEAD"===d.type?C="nocontent":304===t?C="notmodified":(C=b.state,p=b.data,f=!(y=b.error))):(y=C,(t||!C)&&(C="error",t<0&&(t=0))),j.status=t,j.statusText=(n||C)+"",f?v.resolveWith(h,[p,C,j]):v.rejectWith(h,[j,C,y]),j.statusCode(x),x=void 0,c&&g.trigger(f?"ajaxSuccess":"ajaxError",[j,d,f?p:y]),m.fireWith(h,[j,C]),c&&(g.trigger("ajaxComplete",[j,d]),--T.active||T.event.trigger("ajaxStop")))}return j},getJSON:function(e,t,n){return T.get(e,t,n,"json")},getScript:function(e,t){return T.get(e,void 0,t,"script")}}),T.each(["get","post"],function(e,t){T[t]=function(e,n,r,i){return("function"==typeof n||null===n)&&(i=i||r,r=n,n=void 0),T.ajax(T.extend({url:e,type:t,dataType:i,data:n,success:r},T.isPlainObject(e)&&e))}}),T.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),T._evalUrl=function(e,t,n){return T.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,scriptAttrs:t.crossOrigin?{crossOrigin:t.crossOrigin}:void 0,converters:{"text script":function(){}},dataFilter:function(e){T.globalEval(e,t,n)}})},T.fn.extend({wrapAll:function(e){var t;return this[0]&&("function"==typeof e&&(e=e.call(this[0])),t=T(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return"function"==typeof e?this.each(function(t){T(this).wrapInner(e.call(this,t))}):this.each(function(){var t=T(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t="function"==typeof e;return this.each(function(n){T(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){T(this).replaceWith(this.childNodes)}),this}}),T.expr.pseudos.hidden=function(e){return!T.expr.pseudos.visible(e)},T.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},T.ajaxSettings.xhr=function(){return new e.XMLHttpRequest};var ny={0:200};function nm(e){return e.scriptAttrs||!e.headers&&(e.crossDomain||e.async&&0>T.inArray("json",e.dataTypes))}T.ajaxTransport(function(e){var t;return{send:function(n,r){var i,o=e.xhr();if(o.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)o[i]=e.xhrFields[i];for(i in e.mimeType&&o.overrideMimeType&&o.overrideMimeType(e.mimeType),e.crossDomain||n["X-Requested-With"]||(n["X-Requested-With"]="XMLHttpRequest"),n)o.setRequestHeader(i,n[i]);t=function(e){return function(){t&&(t=o.onload=o.onerror=o.onabort=o.ontimeout=null,"abort"===e?o.abort():"error"===e?r(o.status,o.statusText):r(ny[o.status]||o.status,o.statusText,"text"===(o.responseType||"text")?{text:o.responseText}:{binary:o.response},o.getAllResponseHeaders()))}},o.onload=t(),o.onabort=o.onerror=o.ontimeout=t("error"),t=t("abort");try{o.send(e.hasContent&&e.data||null)}catch(e){if(t)throw e}},abort:function(){t&&t()}}}),T.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},converters:{"text script":function(e){return T.globalEval(e),e}}}),T.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),nm(e)&&(e.type="GET")}),T.ajaxTransport("script",function(e){if(nm(e)){var t,n;return{send:function(r,i){t=T(" + + +
+
+ + + \ No newline at end of file diff --git a/edoc/rest2/list-example.xml b/edoc/rest2/list-example.xml new file mode 100644 index 00000000..0de5162c --- /dev/null +++ b/edoc/rest2/list-example.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/edoc/rest2/projects.xqm b/edoc/rest2/projects.xqm new file mode 100644 index 00000000..52e481c4 --- /dev/null +++ b/edoc/rest2/projects.xqm @@ -0,0 +1,575 @@ +xquery version "3.1"; + +module namespace r2p = "https://github.com/dariok/wdbplus/rest2/projects"; + +import module namespace r2 = "https://github.com/dariok/wdbplus/rest2/common" at "rest-common.xqm"; +import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; +import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "../modules/wdb-files.xqm"; + +declare namespace index = "https://github.com/dariok/wdbplus/index"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; + +(:~ + : List all projects + : GET {base}/projects + :) +declare function r2p:listProjects ( $request as map(*) ) as map(*) { + let $projects := doc("/db/apps/edoc/index/project-index.xml")//index:project + + let $result := + + { + for $project in $projects return + + } + + + return r2:returnXmlOrJson($result) +}; + +(:~ + : List all subprojects of a project + : GET /projects/{$parent}/subprojects + :) +declare function r2p:listSubprojects ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?parent) } catch * { $err:code } + + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?parent || ' not found', $r2:allOrigins) + else + let $meta := doc($project?collectionPath || "/wdbmeta.xml") + , $subprojects := $meta//meta:ptr + , $labels := map:merge( + for $struct in $meta//meta:struct + let $file := string($struct/@file) + return map:entry($file, string($struct/@label)) + ) + , $result := + + { + for $entry in $subprojects + let $ed := string($entry/@xml:id) + return + + } + + + return r2:returnXmlOrJson($result) +}; + +(:~ + : Create a subproject, generating an ID + : POST /projects/{$parent}/subprojects + :) +declare function r2p:createProjectWithoutId ( $request as map(*) ) as map(*) { + if ( not(r2:mapKeysAllowed($request?body, ('title', 'collection'), ('short'))) ) then + r2:response(422, 'text/plain', 'Wrong content of project information found. Expected `title` and `collection` (mandatory), or `short`.', $r2:allOrigins) + else + r2p:createProjectWithId( + map{ + "parameters": map{ + "parent": $request?parameters?parent, + "ed": '_' || util:uuid() + }, + "body": $request?body, + "user": $request?user + } + ) +}; + +(:~ + : create a new project with the metadata given in the request + : PUT /projects/{$parent}/subprojects/{$ed} + : also called by r2p:createProjectWithoutId + :) +declare function r2p:createProjectWithId ( $request as map(*) ) as map(*) { + let $parent := try { wdbFiles:getFullPath($request?parameters?parent) } catch * { $err:code } + , $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + + return if ( not(exists($request?parameters?parent)) or not(exists($request?parameters?ed)) ) then + r2:response(400, 'text/plain', 'Bad Request\n parameter `parent` or `ed` missing', $r2:allOrigins) + else if ( not(exists($request?user)) or $request?user?fullName = 'guest' ) then + r2:response(401, 'text/plain', 'Unauthorized', $r2:allOrigins) + else if ( not(r2:writeAllowed($request?user)) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( $parent instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?parent || ' not found', $r2:allOrigins) + else if ( not(sm:has-access($parent?collectionPath, "w")) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( $project instance of map(*) and exists($project?collectionPath) ) then + r2:response(409, 'text/plain', 'A project with ID ' || $request?parameters?ed || ' already exists', $r2:allOrigins) + else if ( xmldb:collection-available($parent?collectionPath || '/' || $request?body?collection) ) then + r2:response(409, 'text/plain', 'A collection with name ' || $request?body?collection || ' already exists in project ' || $request?parameters?parent, $r2:allOrigins) + else if ( not(r2:mapKeysAllowed($request?body, ('title', 'collection'), ('short'))) ) then + r2:response(422, 'text/plain', 'Wrong content of project information found. Expected `title` and `collection`(mandatory), `short`.', $r2:allOrigins) + else + + let $parentCollection := $parent?collectionPath + , $parentMeta := doc( $parentCollection || "/wdbmeta.xml" ) + , $subCollection := xmldb:create-collection($parentCollection, $request?body?collection) + , $newMetaPath := xmldb:copy-resource("/db/apps/edoc/admin/project-template", "wdbmeta.xml", $subCollection, "wdbmeta.xml") + , $collectionPermissions := sm:get-permissions(xs:anyURI($parentCollection)) + , $metaPermissions := sm:get-permissions(xs:anyURI($parentCollection || "/wdbmeta.xml")) + , $meta := doc($newMetaPath) + + return r2:response( + 201, + 'text/plain', + ( + sm:chown(xs:anyURI($subCollection), $collectionPermissions//@owner || ":" || $collectionPermissions//@group), + sm:chmod(xs:anyURI($subCollection), $collectionPermissions//@mode), + sm:chown(xs:anyURI($newMetaPath), $metaPermissions//@owner || ":" || $metaPermissions//@group), + sm:chmod(xs:anyURI($newMetaPath), $metaPermissions//@mode), + + xmldb:create-collection($subCollection, "edition"), + sm:chown(xs:anyURI($subCollection || '/edition'), $collectionPermissions//@owner || ":" || $collectionPermissions//@group), + sm:chmod(xs:anyURI($subCollection || '/edition'), $collectionPermissions//@mode), + + update insert attribute xml:id { $request?parameters?ed } into $meta/meta:projectMD, + update replace $meta//meta:projectID[1] + with { $request?parameters?ed }, + update replace $meta//meta:title[1] + with { $request?body?title }, + update insert attribute label { $request?body?title } into $meta//meta:struct[1], + if ( exists($request?body?short) ) then + update insert + { $request?body?short } + following $meta//meta:title[@type = 'main'][1] + else (), + + update insert + into $parentMeta//meta:files, + update insert + into $parentMeta/meta:projectMD/meta:struct, + + (: copy the full project structure for main projects (i.e., $parent = 'data') only :) + if ( $request?parameters?parent = 'data' ) then + ( + xmldb:create-collection($subCollection, "resources"), + xmldb:create-collection($subCollection || "/resources", "blobs"), + xmldb:create-collection($subCollection || "/resources", "css"), + xmldb:create-collection($subCollection || "/resources", "html"), + xmldb:create-collection($subCollection || "/resources", "images"), + xmldb:create-collection($subCollection || "/resources", "js"), + xmldb:create-collection($subCollection || "/resources", "xq"), + + xmldb:copy-collection("/db/apps/edoc/admin/project-template/resources/xsl", $subCollection || "/resources"), + + sm:chmod(xs:anyURI($subCollection || "/resources"), 'rwxrwxr-x'), + sm:chown(xs:anyURI($subCollection || "/resources"), "wdb:wdbusers"), + for $c in xmldb:get-child-collections($subCollection || "/resources") + return ( + sm:chmod(xs:anyURI($subCollection || "/resources/" || $c), 'rwxrwxr-x'), + sm:chown(xs:anyURI($subCollection || "/resources/" || $c), "wdb:wdbusers") + ), + for $f in xmldb:get-child-resources($subCollection || "/resources/xsl") + return ( + sm:chmod(xs:anyURI($subCollection || "/resources/xsl/" || $f), "rwxrwxr-x"), + sm:chown(xs:anyURI($subCollection || "/resources/xsl/" || $f), "wdb:wdbusers") + ), + + xmldb:copy-resource("/db/apps/edoc/admin/project-template", "project.xqm", $subCollection, "project.xqm"), + sm:chown(xs:anyURI($subCollection || "/project.xqm"), "wdb:wdbusers"), + sm:chmod(xs:anyURI($subCollection || "/project.xqm"), "rwxrwxr-x") + ) + else (), + + $request?parameters?ed + )[last()], (: create-collection() returns a string; we only want the path to the project collection :) + $r2:allOrigins + ) +}; + +(:~ + : List all views for a project + : GET /projects/{$ed}/views + :) +declare function r2p:listProjectViews ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else + r2:returnXmlOrJson( + + + + ) +}; + +(:~ + : Get basic information about a project + : GET /projects/{$ed} + :) +declare function r2p:getProject ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else + let $meta := doc( $project?collectionPath || "/wdbmeta.xml" ) + return r2:returnXmlOrJson( + + { + for $entry in $meta//meta:ptr return + + } + { + for $entry in $meta//meta:file return + + } + + ) +}; + +(:~ + : List all resources of a project + : GET /projects/{$ed}/resources + :) +declare function r2p:listProjectResources ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else + let $meta := doc( $project?collectionPath || "/wdbmeta.xml" ) + , $views := $meta//meta:view + , $result := + + { + for $entry in $views + let $id := string($entry/@file) + return + + } + + return r2:returnXmlOrJson($result) +}; + +(:~ + : Create an XML resource in a project (no ID given) + : This is used for XML files only. Non-XML files need to be created with a full path via PUT, so that the path information is available for the processing of the file. + : POST /projects/{$ed}/resources + :) +declare function r2p:createProjectResourceWithoutId ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + , $meta := try { doc( $project?collectionPath || "/wdbmeta.xml" ) } catch * { $err:code } + , $xml := try { parse-xml($request?body?file?data) } catch * { $err:code } + , $id := if ( $xml instance of node() ) + then ($xml/*[1]/@xml:id, '_' || util:uuid())[1] + else () + , $uuid := util:uuid($xml) + + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else if ( not(starts-with($request?media-type, "multipart/form-data")) ) then + r2:response(415, 'text/plain', 'Unsupported Media Type. Expected multipart/form-data with a file field.', + map:merge(($r2:allOrigins, map:entry("Allow-Post", "multipart/form-data"))) + ) + else if ( not(r2:mapKeysAllowed($request?body, ('path', 'file'), ())) ) then + r2:response(422, 'text/plain', 'Wrong content of resource information found. Expected `path` and `file`.', $r2:allOrigins) + else if ( not($xml instance of document-node()) ) then + r2:response(422, 'text/plain', 'File content is not valid XML.', $r2:allOrigins) + else if ( not(exists($request?user)) or $request?user?fullName = 'guest' ) then + r2:response(401, 'text/plain', 'Unauthorized', $r2:allOrigins) + else if ( not(r2:writeAllowed($request?user)) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( not(sm:has-access($project?collectionPath, "w")) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( $meta//meta:file[@path = $request?body?path || '/' || $request?body?file?name] ) then + r2:response(409, 'text/plain', 'A resource with path ' || $request?body?path || '/' || $request?body?file?name || ' already exists in project ' || $request?parameters?ed, $r2:allOrigins) + else if ( $meta//meta:file[@xml:id = $id] ) then + r2:response(409, 'text/plain', 'A resource with ID ' || $id || ' already exists in project ' || $request?parameters?ed, $r2:allOrigins) + else if ( $meta//meta:file[@uuid = $uuid] ) then + r2:response(409, 'text/plain', 'A resource with a hash of ' || $uuid || ' already exists in project ' || $request?parameters?ed || ' as ' || $meta//meta:file[@uuid = $uuid]/@path, $r2:allOrigins) + else + (: TODO: check media type for non-XML files, and handle accordingly (e.g. store as binary) :) + r2:createXmlResource( + map{ + "parameters": map:merge(( + $request?parameters, + map:entry("id", $id) + )), + "body": map:merge(( + $request?body, + map:entry("xml", $xml), + map:entry("hash", $uuid) + )), + "user": $request?user, + "project": $project + } + ) +}; + +(:~ + : Create a resource in a project (ID given – this may overwrite an existing resource) + : If no entry with this ID, this path, and this hash exists, creates a new resource with the given ID. + : If an entry with this ID but a different path exists, returns a 409 Conflict, + : If an entry with this path but a different ID exists, returns a 409 Conflict, + : If an entry with this hash but a different ID and path exists, returns a 409 Conflict. + : If all three match an existing entry, return 204 + : PUT /projects/{$ed}/resources/{$id} + :) +declare function r2p:createProjectResourceWithId ( $request as map(*) ) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + , $meta := try { doc( $project?collectionPath || "/wdbmeta.xml" ) } catch * { $err:code } + , $xml := try { parse-xml($request?body?file?data) } catch * { $err:code } + , $uuid := util:uuid($xml) + + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else if ( not(starts-with($request?media-type, "multipart/form-data")) ) then + r2:response(415, 'text/plain', 'Unsupported Media Type. Expected multipart/form-data with a file field.', + map:merge(($r2:allOrigins, map:entry("Allow-Post", "multipart/form-data"))) + ) + else if ( not(r2:mapKeysAllowed($request?body, ('path', 'file'), ())) ) then + r2:response(422, 'text/plain', 'Wrong content of resource information found. Expected `path` and `file`.', $r2:allOrigins) + else if ( not($xml instance of document-node()) ) then + r2:response(422, 'text/plain', 'File content is not valid XML.', $r2:allOrigins) + else if ( exists($xml/*[1]/@xml:id) and $xml/*[1]/@xml:id != $request?parameters?id ) then + r2:response(422, 'text/plain', 'ID in the XML content (' || $xml/*[1]/@xml:id || ') does not match the ID in the URL (' || $request?parameters?id || ').', $r2:allOrigins) + else if ( not(exists($request?user)) or $request?user?fullName = 'guest' ) then + r2:response(401, 'text/plain', 'Unauthorized', $r2:allOrigins) + else if ( not(r2:writeAllowed($request?user)) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( not(sm:has-access($project?collectionPath, "w")) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( $meta//meta:file[@path = $request?body?path || '/' || $request?body?file?name + and @xml:id = $request?parameters?id + and @uuid = $uuid + ] ) then + r2:response(204, 'text/plain', '', $r2:allOrigins) + else if ( $meta//meta:file[@path = $request?body?path || '/' || $request?body?file?name and @xml:id != $request?parameters?id] ) then + r2:response(409, 'text/plain', 'A resource with path ' || $request?body?path || ' already exists in project ' || $request?parameters?ed || ' with ID ' || $request?parameters?id, $r2:allOrigins) + else if ( $meta//meta:file[@xml:id = $request?parameters?id and @path != $request?body?path || '/' || $request?body?file?name] ) then + r2:response(409, 'text/plain', 'A resource with ID ' || $request?parameters?id || ' already exists in project ' || $request?parameters?ed || ' with different path ' || $request?body?path || '/' || $request?body?file?name, $r2:allOrigins) + else if ( $meta//meta:file[@uuid = $uuid] ) then + r2:response(409, 'text/plain', 'A resource with a hash of ' || $uuid || ' already exists in project ' || $request?parameters?ed || ' as ' || $meta//meta:file[@uuid = $uuid]/@path, $r2:allOrigins) + else if ( $meta//id($request?parameters?id)[self::meta:struct] ) then + r2:response(409, 'text/plain', 'ID ' || $request?parameters?id || ' is already in use for a struct ' || $meta/id($request?parameters?id)/@label || $meta/id($request?parameters?id)/meta:label, $r2:allOrigins) + else + (: TODO: check media type for non-XML files, and handle accordingly (e.g. store as binary) :) + r2:createXmlResource( + map{ + "parameters": map:merge(( + $request?parameters, + map:entry("id", $request?parameters?id) + )), + "body": map:merge(( + $request?body, + map:entry("xml", $xml), + map:entry("hash", $uuid) + )), + "user": $request?user, + "project": $project + } + ) +}; + +(: +TODO: - add a function to update project information (e.g. title, short title) → PATCH + +TODO: - check whether we need a uniform “descriptor” element for both projects and files in the project metadata + (, so that we can have a single endpoint for listing all resources of a project (instead of separate ones for subprojects and files). This would also make it easier to maintain the order of resources in the project metadata, which is currently not possible with the separate and elements.) + + + { $r2:base }{ $request?path } + { $meta//meta:title[@type = 'main'] } + { + if ( exists($meta//meta:title[@type = 'sub']) ) then + { $meta//meta:title[@type = 'sub'] } + else () + } + + { + for $entry in $meta//meta:ptr return + + } + + + { + for $entry in $meta//meta:file return + + } + + + +:) + +(:~ + : Delete a project + : DELETE /projects/{$ed} + :) +declare function r2p:deleteProject ( $request as map(*) ) as map(*) { + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + , $meta := try { doc( $project?collectionPath || "/wdbmeta.xml" ) } catch * { $err:code } + + return if ( not(exists($request?parameters?ed)) or $request?parameters?ed = '' ) then + r2:response(400, 'text/plain', 'Bad Request: parameter `ed` missing', $r2:allOrigins) + else if ( $request?parameters?ed = 'data' ) then + r2:response(400, 'text/plain', 'Forbidden: main project "data" cannot be deleted', $r2:allOrigins) + else if ( not(exists($request?user)) or $request?user?fullName = 'guest' ) then + r2:response(401, 'text/plain', 'Unauthorized', $r2:allOrigins) + else if ( not(r2:writeAllowed($request?user)) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else if ( not(sm:has-access($project?collectionPath, "w")) ) then + r2:response(403, 'text/plain', 'Forbidden', $r2:allOrigins) + else + let $projectPath := string($project?collectionPath) + , $parentPath := $project?parentProject + , $parentMeta := if ( doc-available($parentPath || "/wdbmeta.xml") ) + then doc($parentPath || "/wdbmeta.xml") + else () + , $projectMeta := if ( doc-available($projectPath || "/wdbmeta.xml") ) + then doc($projectPath || "/wdbmeta.xml") + else () + , $fileIds := if ( $projectMeta ) + then ( + $projectMeta//meta:file/@xml:id/string(), + $projectMeta//meta:struct[@xml:id]/@xml:id/string() + ) + else () + , $subProjectIds := if ( $projectMeta ) + then $projectMeta//meta:ptr/@xml:id/string() + else () + , $collectionName := replace($projectPath, "^.*/", "") + , $projectIndex := doc("/db/apps/edoc/index/project-index.xml") + , $fileIndex := doc("/db/apps/edoc/index/file-index.xml") + + return r2:response( + 204, + 'text/plain', + ( + if ( subProjectIds ) then + for $id in $subProjectIds return r2p:deleteProject(map{ + "parameters": map{ "ed": $id }, + "user": $request?user + }) + else (), + if ( $parentMeta ) then ( + update delete $parentMeta//meta:ptr[@xml:id = $request?parameters?ed], + update delete $parentMeta//meta:struct[@file = $request?parameters?ed] + ) else (), + update delete $projectIndex/id($request?parameters?ed), + for $id in $fileIds return update delete $fileIndex/id($id), + xmldb:remove($projectPath), + '' + )[last()], + $r2:allOrigins + ) +}; + +declare function r2p:viewProject ( $request as map(*) ) as map(*) { + if ( not($request?parameters?view = ('default', 'navigation', 'start')) ) then + r2:response(400, 'text/plain', 'Bad value for parameter `view` + Expected one of "default", "navigation", "start", got ' || $request?parameters?view, $r2:allOrigins) + else if ( ($request?parameters?view = 'default' and request:get-header('Accept') != 'application/xml') + or ($request?parameters?view = 'navigation' and not(request:get-header('Accept') = ('application/xml', 'application/json', 'text/html'))) + or ($request?parameters?view = 'start' and request:get-header('Accept') != 'text/html') ) then + r2:response(406, 'text/plain', 'Available representations are: + for view "default": application/xml + for view "start": text/html + for view "navigation": application/xml, application/json, text/html', $r2:allOrigins) + else + let $project := try { wdbFiles:getFullPath($request?parameters?ed) } catch * { $err:code } + return if ( $project instance of xs:QName ) then + r2:response(404, 'text/plain', 'Project ' || $request?parameters?ed || ' not found', $r2:allOrigins) + else + r2:returnXmlOrJson( + r2p:projectView(map{ + "path" : $project?collectionPath || "/wdbmeta.xml", + "parameters": $request?parameters, + "Accept": request:get-header('Accept') + }) + ) +}; + +declare function r2p:projectView ( $request as map(*) ) as node() { + let $meta := doc($request?path) + return if ( $request?parameters?view = 'start' ) then + wdb:applySpecificXsl($meta, $request?path => substring-before('wdbmeta.xml'), "start.xsl") + else if ( $request?parameters?view = 'navigation' ) then + let $struct := $meta//meta:projectMD/meta:struct + let $content := {( + $struct/@* + , $struct/* + )} + + let $response := if ( $struct/meta:import ) + then r2p:imported($struct/meta:import, $content) + else $content + + return if ( $request?Accept = 'text/html' ) + then wdb:applySpecificXsl($response, $request?path => substring-before('wdbmeta.xml'), "nav.xsl") + else $response + else + $meta +}; + +declare %private function r2p:imported ( $import, $importerContent ) { + let $base-uri := base-uri($import) + , $fullImportedPath := substring-before($base-uri, "wdbmeta.xml") || $import/@path + , $importedMeta := doc($fullImportedPath) + , $importedContent := $importedMeta/meta:projectMD/meta:struct + + let $conStructed := + { $importedContent/@* } + { if ( $importedMeta/@ed ) then () else attribute ed { $importedMeta/meta:projectMD/@xml:id } } + { for $elem in $importedContent/* return + if ( $elem/@file = $importerContent/@ed ) + then $importerContent + else $elem + } + + + return if ( $importedContent/meta:import ) + then r2p:imported($importedContent/meta:import, $conStructed) + else $conStructed +}; diff --git a/edoc/rest2/resources.xqm b/edoc/rest2/resources.xqm new file mode 100644 index 00000000..4e8024dc --- /dev/null +++ b/edoc/rest2/resources.xqm @@ -0,0 +1,334 @@ +xquery version "3.1"; + +module namespace r2r = "https://github.com/dariok/wdbplus/rest2/resources"; + +import module namespace r2 = "https://github.com/dariok/wdbplus/rest2/common" at "rest-common.xqm"; +import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; +import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "../modules/wdb-files.xqm"; +import module namespace wdbProc = "https://github.com/dariok/wdbplus/Process" at "../modules/wdb-process.xqm"; +import module namespace router = "http://e-editiones.org/roaster/router"; + +declare namespace index = "https://github.com/dariok/wdbplus/index"; +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace request = "http://exist-db.org/xquery/request"; +declare namespace sm = "http://exist-db.org/xquery/securitymanager"; +declare namespace tei = "http://www.tei-c.org/ns/1.0"; +declare namespace util = "http://exist-db.org/xquery/util"; +declare namespace wdbErr = "https://github.com/dariok/wdbplus/errors"; +declare namespace xmldb = "http://exist-db.org/xquery/xmldb"; + +declare variable $r2r:allow := "GET, PUT, PATCH, HEAD, OPTIONS, DELETE"; + +declare %private function r2r:headersWithAllow () as map(*) { + map:merge(( + $r2:allOrigins, + map { + "Allow": $r2r:allow, + "Access-Control-Allow-Methods": $r2r:allow + } + )) +}; + +declare %private function r2r:getResourceInfo ( $id as xs:string ) as map(*)? { + let $resource := wdbFiles:getFullPath($id) + + return + if ( $resource?kind != "file" ) then + () + else + let $meta := doc($resource?projectPath || "/wdbmeta.xml") + , $entry := $meta/id($id)[self::meta:file][1] + return + if ( empty($entry) ) then + () + else + map:merge(( + $resource, + map { + "meta": $meta, + "entry": $entry, + "path": $resource?collectionPath || "/" || $resource?fileName + } + )) +}; + +declare %private function r2r:getMimeType ( $path as xs:string, $content as item()? ) as xs:string { + let $mimeType := xmldb:get-mime-type($path) + return + if ( $mimeType = "application/xml" + and $content instance of document-node() + and $content/*[1]/namespace-uri() = "http://www.tei-c.org/ns/1.0" ) then + "application/tei+xml" + else + $mimeType +}; + +declare %private function r2r:getStoredContent ( $path as xs:string ) as item()? { + if ( doc-available($path) ) then + doc($path) + else if ( util:binary-doc-available($path) ) then + util:binary-doc($path) + else + () +}; + +declare %private function r2r:requireWritableResource ( $request as map(*) ) as map(*) { + let $resource := try { + r2r:getResourceInfo($request?parameters?id) + } catch * { () } + + return + if ( not(exists($request?user)) or $request?user?fullName = "guest" ) then + map { "error": r2:response(401, "text/plain", "Unauthorized", $r2:allOrigins) } + else if ( not(r2:writeAllowed($request?user)) ) then + map { "error": r2:response(403, "text/plain", "Forbidden", $r2:allOrigins) } + else if ( empty($resource) ) then + map { "error": r2:response(404, "text/plain", "File " || $request?parameters?id || " not found", $r2:allOrigins) } + else if ( not(sm:has-access($resource?path, "w")) ) then + map { "error": r2:response(403, "text/plain", "Forbidden", $r2:allOrigins) } + else + $resource +}; + +declare %private function r2r:parseUpload ( $request as map(*) ) as map(*)? { + if ( not(starts-with($request?media-type, "multipart/form-data")) ) then + map { "error": r2:response(415, "text/plain", "Unsupported Media Type. Expected multipart/form-data with a file field.", $r2:allOrigins) } + else if ( not(r2:mapKeysAllowed($request?body, ("path", "file"), ())) ) then + map { "error": r2:response(400, "text/plain", "Wrong content of resource information found. Expected `path` and `file`.", $r2:allOrigins) } + else + let $xml := try { parse-xml($request?body?file?data) } catch * { () } + return + if ( empty($xml) ) then + map { "error": r2:response(400, "text/plain", "File content is not valid XML.", $r2:allOrigins) } + else + map { + "xml": $xml, + "hash": util:uuid($xml), + "relativePath": $request?body?path || "/" || $request?body?file?name + } +}; + +declare %private function r2r:getViewsXml ( $resource as map(*) ) as element(list) { + let $processes := $resource?meta//meta:process[@target] + return + + { + for $process in $processes + let $viewName := string(($process/@view, 'default')[1]) + return + + } + +}; + +declare %private function r2r:resolveProcess ( $resource as map(*), $view as xs:string, $target as xs:string ) as element(meta:process)? { + try { + wdb:getXslFromWdbMeta( + $resource?projectPath || "/wdbmeta.xml", + $resource?entry/@xml:id, + substring-after($target, '/'), (: target is now evaluated from the Accept header which will be a full MIME type :) + if ( $view = 'default' ) then () else $view (: process in wdbmeta may not have @view, which means it is default :) + ) + } catch * { + () + } +}; + +declare function r2r:headResource ( $request as map(*) ) as item() { + r2r:returnResource($request, "HEAD") +}; +declare function r2r:getResource ( $request as map(*) ) as item() { + r2r:returnResource($request, "GET") +}; + +declare %private function r2r:returnResource ( $request as map(*), $method as xs:string ) as item() { + let $resource := try { + r2r:getResourceInfo($request?parameters?id) + } catch * { () } + + return if ( empty($resource) ) then + r2:response(404, "text/plain", "No resource found by this ID", $r2:allOrigins) + else + let $content := r2r:getStoredContent($resource?path) + , $lastModified := wdbFiles:ietfDate(wdbFiles:getModificationDate($resource?collectionPath, $resource?fileName)) + , $mimeType := r2r:getMimeType($resource?path, $content) + , $modified := request:get-header("If-Modified-Since") + , $status := if ( exists($modified) and $modified != "" ) + then wdbFiles:evaluateIfModifiedSince($resource?collectionPath, $resource?fileName, $modified) + else 200 + + return if ( empty($content) ) then + r2:response(204, "", "", $r2:allOrigins) + else + router:response( + $status, + $mimeType, + if ( $method = "GET" ) then $content else (), + map:merge(($r2:allOrigins, map { "Last-Modified": $lastModified })) + ) +}; + +declare function r2r:putResource ( $request as map(*) ) as item() { + let $resource := r2r:requireWritableResource($request) + return if ( exists($resource?error) ) then + $resource?error + else + let $upload := r2r:parseUpload($request) + return if ( exists($upload?error) ) then + $upload?error + else if ( exists($upload?xml/*[1]/@xml:id) and $upload?xml/*[1]/@xml:id != $request?parameters?id ) then + r2:response(400, "text/plain", "ID in the XML content (" || $upload?xml/*[1]/@xml:id || ") does not match the ID in the URL (" || $request?parameters?id || ").", $r2:allOrigins) + else if ( $upload?relativePath != string($resource?entry/@path) ) then + r2:response(409, "text/plain", "A file with ID " || $request?parameters?id || " is present in a different location: " || $resource?entry/@path, $r2:allOrigins) + else + let $existingDoc := try { doc($resource?path) } catch * { () } + , $existingHash := if ( exists($existingDoc) ) then util:uuid($existingDoc) else () + return if ( exists($existingHash) and $existingHash = $upload?hash ) then + r2:response(204, "text/plain", "", $r2:allOrigins) + else + r2:createXmlResource( + map{ + "parameters": map { + "id": $request?parameters?id + }, + "body": map:merge(( + $request?body, + map { + "xml": $upload?xml, + "hash": $upload?hash + } + )), + "user": $request?user, + "project": map { + "collectionPath": $resource?projectPath + } + } + ) +}; + +declare function r2r:patchResource ( $request as map(*) ) as item() { + let $resource := r2r:requireWritableResource($request) + return if ( exists($resource?error) ) then + $resource?error + else + let $content := try { doc($resource?path) } catch * { () } + , $patch := if ( $request?body instance of document-node() ) then $request?body else try { parse-xml($request?body) } catch * { () } + return if ( empty($content) ) then + r2:response(404, "text/plain", "File " || $request?parameters?id || " not found", $r2:allOrigins) + else if ( empty($patch) or empty($patch/*[1]/@xml:id) ) then + r2:response(400, "text/plain", "Patch body must be a well-formed XML fragment with xml:id.", $r2:allOrigins) + else + let $target := $content/id($patch/*[1]/@xml:id) + return if ( empty($target) ) then + r2:response(400, "text/plain", "No fragment with xml:id " || $patch/*[1]/@xml:id || " found in resource " || $request?parameters?id, $r2:allOrigins) + else + let $updated := ( + update replace $target with $patch/*[1], + xmldb:store($resource?collectionPath, $resource?fileName, $content, xmldb:get-mime-type($resource?path)) + ) + return r2:response(204, "text/plain", "", $r2:allOrigins) +}; + +declare function r2r:optionsResource ( $request as map(*) ) as item() { + let $resource := r2r:getResourceInfo($request?parameters?id) + , $t := util:log("info", "OPTIONS request for resource with ID " || $request?parameters?id || ". Resource found: " || empty($resource)) + return if ( empty($resource) ) then + r2:response(404, "text/plain", "File " || $request?parameters?id || " not found", $r2:allOrigins) + else + r2:response(204, "text/plain", "", r2r:headersWithAllow()) +}; + +declare function r2r:deleteResource ( $request as map(*) ) as item() { + let $resource := r2r:requireWritableResource($request) + return if ( exists($resource?error) ) then + $resource?error + else + r2:response( + 204, + "text/plain", + ( + xmldb:remove($resource?collectionPath, $resource?fileName), + update delete $resource?meta//meta:file[@xml:id = $request?parameters?id], + update delete $resource?meta//meta:view[@file = $request?parameters?id], + update delete doc("/db/apps/edoc/index/file-index.xml")/index:index/id($request?parameters?id), + "" + )[last()], + $r2:allOrigins + ) +}; + +declare function r2r:listResourceViews ( $request as map(*) ) as item() { + let $resource := try { + r2r:getResourceInfo($request?parameters?id) + } catch * { () } + + return if ( empty($resource) ) then + r2:response(404, "text/plain", "File " || $request?parameters?id || " not found", $r2:allOrigins) + else + r2:returnXmlOrJson(r2r:getViewsXml($resource)) +}; + +declare function r2r:getResourceView ( $request as map(*) ) as item() { + let $resource := try { + r2r:getResourceInfo($request?parameters?id) + } catch * { () } + + return if ( empty($resource) ) then + r2:response(404, "text/plain", "The resource was not found", $r2:allOrigins) + else + let $type := if ( exists($request?parameters?accept) ) + then $request?parameters?accept + else "text/html" + , $process := try { + r2r:resolveProcess($resource, $request?parameters?view, $type) + } catch wdbErr:wdb0002 { () } + + let $modified := request:get-header("If-Modified-Since") + , $status := if ( exists($modified) and $modified != "" ) + then wdbFiles:evaluateIfModifiedSince($resource?collectionPath, $resource?fileName, $modified) + else 200 + + return if ( empty($process) ) then + r2:response(406, "application/xml", r2r:getViewsXml($resource), $r2:allOrigins) + else if ( $status = 304 ) then + r2:response(304, "text/plain", "", $r2:allOrigins) + else + let $viewParam := string($process/@view) + , $result := wdbProc:getContent( + $request?parameters?id, + $process, + $viewParam, + map { + "id": $request?parameters?id, + "process": $process, + "view": $viewParam, + "fileLoc": $resource?path, + "pathToEd": $resource?projectPath, + "ed": tokenize(normalize-space($resource?projectPath), "/")[last()], + "xslt": $process + } + ) + , $body := $result?content + , $namespace := if ( $body instance of document-node() or $body instance of element() ) + then namespace-uri(($body/*[1], $body)[1]) + else () + , $mimeType := wdb:getContentTypeFromExt(string($process/@target), $namespace) + return router:response($result?status, $mimeType, $body, $r2:allOrigins) +}; + +declare function r2r:getResourceByPid ( $request as map(*) ) as item() { + let $matches := collection("/db/apps/edoc/data")//meta:file[@pid = $request?parameters?pid] + return if ( count($matches) = 1 ) then + r2:response(200, "text/plain", string($matches[1]/@xml:id), $r2:allOrigins) + else + r2:response(404, "text/plain", "This external PID was not found", $r2:allOrigins) +}; diff --git a/edoc/rest2/rest-common.xqm b/edoc/rest2/rest-common.xqm new file mode 100644 index 00000000..f325c9f7 --- /dev/null +++ b/edoc/rest2/rest-common.xqm @@ -0,0 +1,233 @@ +xquery version "3.1"; + +module namespace r2 = "https://github.com/dariok/wdbplus/rest2/common"; + +import module namespace router = "http://e-editiones.org/roaster/router"; +import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "../modules/app.xqm"; + +declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta"; +declare namespace sm = "http://exist-db.org/xquery/securitymanager"; +declare namespace tei = "http://www.tei-c.org/ns/1.0"; + +declare variable $r2:acceptable := ("application/json", "application/xml", "text/html"); + +(:~ + : Base URL for the REST API + :) +declare variable $r2:base := doc('../config.xml')//*:rest[@version = "2"]; + +(:~ + : list of allowed origins + :) +declare variable $r2:origins := doc('../config.xml')//*:origins/*; + +declare variable $r2:allOrigins := if ( request:get-header('origin') != '' ) + then map { + "Access-Control-Allow-Origin" : request:get-header('origin'), + "Access-Control-Allow-Credentials" : "true" + } + else map { + "Access-Control-Allow-Origin" : "*" + }; +(: , + "Access-Control-Allow-Methods" : "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers" : "Content-Type, Authorization", + "Access-Control-Max-Age" : "86400" :) + +declare variable $r2:mediaTypes := map { + "Access-Control-Allow-Origin": "*", + "AllowPost": string-join($r2:acceptable, ' ') +}; + +declare function r2:returnXmlOrJson ( $data as item() ) as item() { + let $mediaType := request:get-header("Accept") + return + if ( $mediaType = "application/json" ) then + router:response(200, "application/json", parse-json(xml-to-json(transform:transform($data, doc('api.xsl'), ()))), $r2:allOrigins) + else if ( $mediaType = $r2:acceptable ) then ( + router:response(200, $mediaType, $data, $r2:allOrigins) + ) + else + router:response(406, "text/plain", "Not acceptable", $r2:allOrigins) +}; + +declare function r2:response ( $status as xs:integer, $mediaType as xs:string, $body as item(), $headers as map(*) ) as item() { + router:response($status, $mediaType, $body, $headers) +}; + +declare function r2:parseBody ( $request as map(*) ) as item() { + let $mediaType := $request?media-type + (: , $t1 := util:log("info", $request?body) :) + (: , $checkMediaType := $mediaType = $r2:acceptable :) + (: , $t0 := util:log("info", $mediaType || ': ' || $checkMediaType) :) + + return + (: Roaster should handle unsupported media types and return 415 :) + (: if ( not($checkMediaType) ) then + ( util:log("error", "unsupported: " || $mediaType), + r2:response(415, 'text/plain', 'Unsupported Media Type', $r2:mediaTypes) + ) + else :) + if ( $mediaType = "application/json" and $request?body instance of map(*) ) then + $request?body?title + else if ( $mediaType = "application/xml" ) then + $request?body + else + "I don’t know what to do…!" +}; + +declare function r2:writeAllowed ( $user as map(*) ) as xs:boolean { + $user?groups = ('dba', 'wdbadmin') +}; + +declare function r2:mapKeysAllowed( + $m as map(*) , + $required as xs:string*, + $optional as xs:string* +) as xs:boolean { + let $keys := map:keys($m) + let $allowed := ($required, $optional) + return + (every $r in $required satisfies $r = $keys) + and + (every $k in $keys satisfies $k = $allowed) +}; + +(:~ + : Function to create a new XML resource or update an existing XML, used for POST and PUT requests. + : XML files are always entered into a wdbmeta file + :) +declare function r2:createXmlResource ( $request as map(*) ) as map(*) { + (: functions in r2p parse the XML to check for valid data type and ID, and thus pass on a parsed XML. + all checks should have been carried out in r2p and r2f functions; hence, we don’t catch :) + let $namespace := namespace-uri($request?body?xml/*[1]) + , $extension := tokenize($request?body?file?name, '\.')[last()] + , $tryType := wdb:getContentTypeFromExt($extension, $namespace) + , $mimeType := if ( $tryType != 'application/octet-stream' ) + then $tryType + else if ( exists($request?body?file?type) ) + then $request?body?file?type + else error() + + , $meta := doc($request?project?collectionPath || "/wdbmeta.xml") + (: checks for conflicts have been done in projects.xqm; this should either be exactly one meta:file or empty :) + , $existing := $meta//id($request?parameters?id) + + , $targetPath := $request?project?collectionPath || $request?body?path + + , $store := ( + r2:store($targetPath, $request?body?file?name, $request?body?xml, $mimeType), + r2:enterMetaForXml($request) + ) + (: note: we do not need to update the file index here as this is done automatically by the update trigger :) + + , $status := if ( exists($existing) ) then 204 else 201 + + return router:response($status, $mimeType, $store, $r2:allOrigins) +}; + +declare function r2:store ( $collection as xs:string, $resource-name as xs:string, $contents as item(), $mime-type as xs:string ) as xs:string { + (: all checks should have been carried out by the higher API functions in r2p and r2f. + Hence, we assume everything’s okay and do not catch errors :) + ( + xmldb:store($collection, $resource-name, $contents, $mime-type), + sm:chmod(xs:anyURI(string-join(($collection, $resource-name), '/')), if ( ends-with($resource-name, 'xql') ) then "rwxrwxr-x" else "rw-rw-r--"), + sm:chown(xs:anyURI(string-join(($collection, $resource-name), '/')), "wdb"), + sm:chgrp(xs:anyURI(string-join(($collection, $resource-name), '/')), "wdbusers") + ) +}; + +declare function r2:enterMetaForXml ( $info as map(*) ) as empty-sequence() { + let $meta := doc($info?project?collectionPath || '/wdbmeta.xml') + , $uuid := $info?body?hash + , $relPath := $info?body?path || '/' || $info?body?file?name + , $id := $info?parameters?id + , $metaFileById := $meta/id($id)[self::meta:file] + , $metaFileByPath := $meta//meta:file[@path = $relPath] + , $metaFile := if ( empty($metaFileById) ) then + $metaFileByPath + else if ( empty($metaFileByPath) ) then + $metaFileById + else if ( $metaFileById[1] is $metaFileByPath[1] ) then + $metaFileById[1] + else + ($metaFileById, $metaFileByPath) + , $errorNonMatch := count($metaFile) = 2 + , $errorNum := count($metaFileById) > 1 or count($metaFileByPath) > 1 + , $errors := if ( $errorNonMatch or $errorNum ) + then + if ( $errorNonMatch ) then error("Conflicting entries for ID " || $id || " and path " || $info?project?collectionPath || $info?body?path || '/' || $info?body?file?name || " in " || base-uri($meta)) + else if ( $errorNum ) then error("More than 2 entries found for ID " || $id || " and path " || $info?project?collectionPath || $info?body?path || '/' || $info?body?file?name || " in " || base-uri($meta)) + else error("unknown error") + else () + + , $file := element { QName("https://github.com/dariok/wdbplus/wdbmeta", "file") } { + if ( count($metaFile) = 1 ) then + for $attr in $metaFile[1]/@* + return if ( + (namespace-uri($attr) = "http://www.w3.org/XML/1998/namespace" and local-name($attr) = "id") + or (namespace-uri($attr) = "" and local-name($attr) = ("path", "date", "uuid")) + ) then () + else $attr + else (), + attribute xml:id { $id }, + attribute path { $relPath }, + attribute date { current-dateTime() }, + attribute uuid { $uuid } + } + , $view := if ( wdb:findProjectFunction(map{"pathToEd": $info?project}, "getRestView", 1) ) + then wdb:eval("wdbPF:getRestView($fileID)", false(), (xs:QName("fileID"), $id)) + else + + { + if ( $info?body?xml//tei:titleStmt/tei:title[@type eq 'num'] ) + then attribute order { normalize-space($info?body?xml//tei:titleStmt/tei:title[@type eq 'num']) } + else () + } + + , $errorContent := map { "errors": $errors, "file": $file, "view": $view } + + return if ( not($errors) and count($metaFile) = 0 ) then + ( + update insert $file into $meta//meta:files, + update insert $view into $meta/meta:projectMD/meta:struct + ) + else if ( not($errors) and count($metaFile) = 1 ) then + ( + update replace $metaFile[1] with $file, + update replace $meta//meta:view[@file = $id] with $view + ) + else ( + r2:logMap($errorContent, 0), + error(xs:QName("wdb:wdb4711"), "Error processing metadata for file ID " || $id, $errorContent) + ) +}; + +declare function r2:logMap ( $request as map(*), $depth as xs:integer ) as item()* { + let $c := for $key in map:keys($request) return + let $ind := string-join((string-join((1 to $depth) ! ' ', '') || $key, ': '), '') + return if( $request($key) instance of map(*) ) then + ( $ind, r2:logMap($request($key), $depth + 1)) + else if ( $request($key) instance of array(*) ) then + $ind || 'Array[' || array:size($request($key)) || ']' + else if ( $request($key) instance of document-node() or $request($key) instance of element() ) then + $ind || 'XML[' || string-length($request($key)) || ']' + else if ( $request($key) instance of xs:string ) then + $ind || 'String[' || string-length($request($key)) || ']' + else if ( $request($key) castable as xs:double ) then + $ind || 'number = ' || string($request($key)) + else if ( $request($key) instance of xs:boolean ) then + $ind || 'boolean = ' || string($request($key)) + else + $ind || ($request($key)) + + return if ( $depth = 0 ) then + util:log("info", "Request content: +" || string-join($c, ' +')) + else + string-join($c, ' +') +}; diff --git a/edoc/rest2/v2.yaml b/edoc/rest2/v2.yaml new file mode 100644 index 00000000..0c9eadc1 --- /dev/null +++ b/edoc/rest2/v2.yaml @@ -0,0 +1,1401 @@ +openapi: 3.0.0 +info: + description: "wdb+ API v2 (wdb+ > v4.0) – see https://github.com/dariok/wdbplus for details" + version: "2.0" + title: "wdb+ API" + # termsOfService: "see instance" + contact: + url: https://github.com/dariok/wdbplus + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: http://localhost:8080/exist/apps/edoc +tags: + - name: auth + description: Operations concerning authentication + # - name: annotations + # description: Concerning Hobbits + - name: projects + description: Operations on wdb+ projects + # - name: entities + # description: Operations on entities + # - name: resources + # description: Operations on resources (usually texts) + # - name: search + # description: Full text search + # - name: oai + # description: OAI PMH endpoints + # - name: dts + # description: Endpoints for Distributed Text Services +security: + - cookieAuth: [] +paths: + /api/v2/login: + post: + summary: "User Login" + description: "Start an authenticated session for the given user" + tags: [ "auth" ] + operationId: "auth:login" + requestBody: + required: true + content: + multipart/form-data: + schema: + "$ref": "#/components/schemas/login" + application/x-www-form-urlencoded: + schema: + "$ref": "#/components/schemas/login" + responses: + '200': + description: "OK" + content: + application/json: + schema: + type: object + properties: + user: + type: string + groups: + type: array + items: + type: string + dba: + type: boolean + domain: + type: string + '401': + description: "Wrong user or password" + security: + - cookieAuth: [] + /api/v2/logout: + get: + summary: User Logout + description: End session of the current user + operationId: 'auth:logout' + tags: + - auth + parameters: + - name: logout + in: query + description: Set to some value to log out the current user + schema: + type: string + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + + # TODO – this should only contain functions that are not already covered by the other endpoint (if any): + # /api/v2/admin + + # /api/v2/annotations: + # post: + # tags: + # - annotations + # summary: Add a new full text annotation + # description: "Create a new full text annotation; return its location when sucessful.
**Note:** 1. no checks are performed and multiple requests will create multiple entries. 2. This creates full text annotations only. Changes to the file, including entity markup, must be made using → `PATCH /resources/{id}`" + # operationId: #TODO + # requestBody: + # $ref: "#/components/requestBodies/annotation" + # responses: + # "201": + # $ref: "#/components/responses/created" + # "400": + # $ref: "#/components/responses/invalidBody" + # /api/v2/annotations/{annotation}: + # parameters: + # - name: "annotation" + # in: path + # description: The ID of the annotation + # schema: + # type: string + # required: true + # get: + # tags: + # - annotations + # summary: Get annotation by ID + # operationId: TODO getAnnotationById + # responses: + # "200": + # description: Annotation has been found + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/annotation.json" + # application/xml: + # schema: + # $ref: "#/components/schemas/annotation.xml" + # "404": + # description: No annotation found by this ID + # put: + # tags: + # - annotations + # summary: Update an annotation + # requestBody: + # $ref: "#/components/requestBodies/annotation" + # responses: + # "204": + # description: Update sucessful. + # "400": + # $ref: "#/components/responses/invalidBody" + # "404": + # description: No annotation found by this ID + # delete: + # tags: + # - annotations + # summary: Delete an annotation + # operationId: #TODO deleteAnnotation + # responses: + # "204": + # description: The annotation has been deleted + # "404": + # description: This annotation was not found + # /api/v2/annotations/forFile/{id}: + # parameters: + # - $ref: "#/components/parameters/id" + # get: + # tags: + # - annotations + # summary: List of annotations related to a file + # operationId: #TODO + # responses: + # "200": + # description: Found annotations for this file + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/listAnnotations" + # application/xml: + # schema: + # $ref: "#/components/schemas/listAnnotations" + # "204": + # description: No annotations for this file + # "404": + # description: File $id not found + + /api/v2/projects: + get: + tags: + - projects + summary: List all projects + operationId: r2p:listProjects + responses: + "200": + $ref: '#/components/responses/projects' + + /api/v2/projects/{ed}: + parameters: + - $ref: "#/components/parameters/ed" + # TODO: should this endpoint also return metadata? + get: + tags: + - projects + summary: Get project contents (registered resources and subprojects) by ID + operationId: r2p:getProject + responses: + "200": + $ref: "#/components/responses/projectContents" + "204": + description: The project was found but currently has neither subprojects nor registered resources + "404": + description: No project found by this ID + delete: + tags: + - projects + summary: Delete project + operationId: r2p:deleteProject + responses: + "204": + description: The project has been deleted + "404": + description: This project was not found + + /api/v2/projects/{parent}/subprojects: + parameters: + - $ref: "#/components/parameters/parent" + get: + tags: + - projects + summary: Get a list of all subprojects of ${parent} + operationId: r2p:listSubprojects + responses: + "200": + $ref: "#/components/responses/projects" + "204": + description: The project was found but currently has neither subprojects nor registered resources + "404": + description: Project $parent not found + post: + tags: + - projects + summary: Create a project in ${parent} without specifying an ID + description: Create a project as child of ${parent} with the meta data provided in the body while auto-generating the ID. E.g., creating a new main project requires "data" as parent. + operationId: r2p:createProjectWithoutId + requestBody: + $ref: "#/components/requestBodies/project" + responses: + "201": + $ref: "#/components/responses/created" + "400": + $ref: "#/components/responses/invalidBody" + "401": + $ref: "#/components/responses/authenticate" + "404": + description: Project $parent not found + "415": + description: Unsupported Media Type. Check the Allow and Allow-Encoding headers. + "422": + description: Unprocessable Entity. The request was well-formed but was unable to be followed due to semantic errors in the body. + security: + - cookieAuth: [] + + /api/v2/projects/{parent}/subprojects/{ed}: + parameters: + - $ref: "#/components/parameters/parent" + - $ref: "#/components/parameters/ed" + put: + tags: + - projects + summary: Create project with given ID + description: This creates a new or updates an existing project with the ID given as ed and the necessary meta data in the request body + operationId: r2p:createProjectWithId + requestBody: + $ref: "#/components/requestBodies/project" + responses: + "201": + $ref: "#/components/responses/created" + "400": + $ref: "#/components/responses/invalidBody" + "401": + $ref: "#/components/responses/authenticate" + "404": + description: Project $parent not found + "409": + description: A project exists with this ID in a different location or the location requested contains a project with a different ID + "415": + description: Unsupported Media Type. Check the Allow and Allow-Encoding headers. + "422": + description: Unprocessable Entity. The request was well-formed but was unable to be followed due to semantic errors in the body. + + /api/v2/projects/{ed}/views: + parameters: + - $ref: "#/components/parameters/ed" + get: + tags: + - projects + summary: get a list of the views available for this project + operationId: r2p:listProjectViews + responses: + "200": + $ref: "#/components/responses/views" + "404": + description: Project $ed not found + + /api/v2/projects/{ed}/views/{view}: + parameters: + - $ref: "#/components/parameters/ed" + - $ref: "#/components/parameters/view" + get: + tags: + - projects + summary: Get project navigation + operationId: r2p:viewProject + responses: + "200": + description: Returning navigation + content: + "application/xml": + example: + "application/json": + example: 'struct { view [ { id: "...", label: "..."} ] }' + "text/html": + example: + "404": + description: Project $ed not found + "406": + description: The media type requested in an 'Accept' header cannot be created for this view + + + /api/v2/projects/{ed}/resources: + parameters: + - $ref: "#/components/parameters/ed" + get: + tags: + - projects + summary: List resources in a project + operationId: r2p:listProjectResources + responses: + "200": + $ref: "#/components/responses/files" + "204": + description: The project was found but currently has no registered resources + "404": + description: Project $ed not found + post: + tags: + - projects + summary: Create a resource in a project (create an ID if necessary) + operationId: r2p:createProjectResourceWithoutId + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - path + - file + properties: + path: + type: string + description: Relative path inside the project (e.g. "texts/foo.xml") + file: + type: string + format: binary + responses: + "201": + $ref: "#/components/responses/created" + "400": + $ref: "#/components/responses/invalidBody" + "401": + $ref: "#/components/responses/authenticate" + "403": + description: Forbidden + "404": + description: Project $ed not found + "409": + description: A file with this ID or file name is already present + "415": + description: Unsupported Media Type. Check the Allow and Allow-Encoding headers. + "422": + description: Invalid or incomplete information in the request body + security: + - cookieAuth: [] + + /api/v2/projects/{ed}/resources/{id}: + parameters: + - $ref: "#/components/parameters/ed" + - $ref: "#/components/parameters/id" + put: + tags: + - projects + summary: Create a resource in a project (with a given ID – this does not update resources) + operationId: r2p:createProjectResourceWithId + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + required: + - path + - file + properties: + path: + type: string + description: Relative path inside the project (e.g. "texts/foo.xml") + file: + type: string + format: binary + responses: + "204": + description: File has been updated + "400": + $ref: "#/components/responses/invalidBody" + "401": + $ref: "#/components/responses/authenticate" + "403": + description: Forbidden + "404": + description: File $id not found in project $ed + "409": + description: A file with this ID is present in a different location or a file in this location exists with a different ID + "415": + description: Unsupported Media Type. Check the Allow and Allow-Encoding headers. + "422": + description: Invalid or incomplete information in the request body + security: + - cookieAuth: [] + + # /api/v2/projects/{ed}/metadata + # get: + # patch: + # put: + + # /api/v2/entities: + # get: + # tags: + # - entities + # summary: Query entities in global registry + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/q" + # - $ref: "#/components/parameters/type" + # - $ref: "#/components/parameters/start" + # responses: + # "200": + # $ref: "#/components/responses/entities" + # "204": + # description: No entities were found for the combination of query parameters + # post: + # tags: + # - entities + # summary: Create a global entity without specifying an ID + # operationId: #TODO + # requestBody: + # $ref: "#/components/requestBodies/entity" + # responses: + # "201": + # $ref: "#/components/responses/created" + # "400": + # $ref: "#/components/responses/invalidBody" + # "409": + # description: The body contains an ID for which an entity is already present + # /api/v2/entities/{entity}: + # get: + # tags: + # - entities + # summary: Get details of entity + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/entity" + # responses: + # "200": + # $ref: "#/components/responses/entity" + # "404": + # description: Entity not found + # put: + # tags: + # - entities + # summary: Create a global entity specifying an ID + # operationId: #TODO + # requestBody: + # $ref: "#/components/requestBodies/entity" + # responses: + # "201": + # $ref: "#/components/responses/created" + # "204": + # description: The entity was updated + # "400": + # $ref: "#/components/responses/invalidBody" + # "404": + # description: Entity $ed not found + # "409": + # description: The body contains an ID for which an entity is already present + # delete: + # tags: + # - entities + # summary: Delete global entity + # operationId: #TODO + # responses: + # "204": + # description: The entity has been deleted + # "404": + # description: This entity was not found + # /api/v2/entities/project/{ed}: + # get: + # tags: + # - entities + # summary: Query entities in a project’s registry + # parameters: + # - $ref: "#/components/parameters/ed" + # - $ref: "#/components/parameters/q" + # - $ref: "#/components/parameters/type" + # - $ref: "#/components/parameters/start" + # operationId: #TODO + # responses: + # "200": + # $ref: "#/components/responses/entities" + # "204": + # description: No entities were found for the combination of query parameters + # "404": + # description: No project by the given ID + # post: + # tags: + # - entities + # summary: Create an entity with a project without specifying an ID + # operationId: #TODO + # requestBody: + # $ref: "#/components/requestBodies/entity" + # responses: + # "201": + # $ref: "#/components/responses/created" + # "400": + # $ref: "#/components/responses/invalidBody" + # "409": + # description: The body contains an ID for which an entity is already present + # /api/v2/entities/project/{ed}/{entity}: + # get: + # tags: + # - entities + # summary: Get details of project entity + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/entity" + # responses: + # "200": + # $ref: "#/components/responses/entity" + # "404": + # description: Entity not foun + # put: + # tags: + # - entities + # summary: Create a project entity specifying an ID + # operationId: #TODO + # requestBody: + # $ref: "#/components/requestBodies/entity" + # responses: + # "201": + # $ref: "#/components/responses/created" + # "204": + # description: The entity was updated + # "400": + # $ref: "#/components/responses/invalidBody" + # "404": + # description: Project $ed or entity $entity not found + # "409": + # description: The body contains an ID for which an entity is already present + # delete: + # tags: + # - entities + # summary: Delete project entity + # operationId: #TODO + # responses: + # "204": + # description: The entity has been deleted + # "404": + # description: This entity was not found + # /api/v2/entities/refs/{entity}: + # parameters: + # - $ref: "#/components/parameters/entity" + # get: + # tags: + # - entities + # summary: List projects referring to an entity + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/start" + # responses: + # "200": + # $ref: "#/components/responses/projects" + # "204": + # description: No references to the queried entity were found + # /api/v2/entities/refs/project/{ed}/{entity}: + # parameters: + # - $ref: "#/components/parameters/ed" + # - $ref: "#/components/parameters/entity" + # get: + # tags: + # - entities + # summary: List texts in a project referring to an entity + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/start" + # responses: + # "200": + # $ref: "#/components/responses/files" + # "204": + # description: No references to the queried entity were found + # "404": + # description: The project was not found + # /api/v2/entities/refs/resource/{id}/{entity}: + # parameters: + # - $ref: "#/components/parameters/id" + # - $ref: "#/components/parameters/entity" + # get: + # tags: + # - entities + # summary: List all fragments in a text containing a reference to an entity + # operationId: #TODO + # parameters: + # - $ref: "#/components/parameters/start" + # responses: + # "200": + # $ref: "#/components/responses/fragments" + # "204": + # description: No references to the queried entity were found + # "404": + # description: The project was not found + + /api/v2/resources/{id}: + parameters: + - $ref: "#/components/parameters/id" + get: + tags: + - resources + summary: Get resource by ID + operationId: "r2r:getResource" + responses: + "200": + description: Resource by ID + content: + "application/tei+xml": + schema: + $ref: "#/components/schemas/TEI" + "404": + description: No resource found by this ID + put: + tags: + - resources + summary: Replace a file + operationId: "r2r:putResource" + requestBody: + description: Replace a file in-place + required: true + content: + multipart/form-data: + schema: + type: object + properties: + path: + type: string + file: + type: string + format: binary + responses: + "201": + $ref: "#/components/responses/created" + "204": + description: File has been updated + "400": + $ref: "#/components/responses/invalidBody" + "404": + description: File $id not found + "409": + description: A file with this ID is present in a different location or a file in this location exists with a different ID + patch: + tags: + - resources + summary: Change a fragment from a file + operationId: "r2r:patchResource" + requestBody: + description: The replacement XML fragment + required: true + content: + "application/xml": + example: "
" + responses: + "204": + description: File has been updated + "400": + $ref: "#/components/responses/invalidBody" + "404": + description: File $id not found + head: + tags: + - resources + summary: Preflight request + operationId: "r2r:headResource" + responses: + "204": + description: File was found + "404": + description: File $id not found + "409": + description: A file with this ID is present in a different location or a file in this location exists with a different ID + options: + tags: + - resources + summary: Preflight request + operationId: "r2r:optionsResource" + responses: + "204": + description: File was found + "404": + description: File $id not found + delete: + tags: + - resources + summary: delete a file + operationId: "r2r:deleteResource" + responses: + "204": + description: File was deleted + "404": + description: File $id not found + /api/v2/resources/{id}/views: + parameters: + - $ref: "#/components/parameters/id" + get: + tags: + - resources + summary: List views for a file + operationId: "r2r:listResourceViews" + responses: + "200": + description: Returns a list of available views + content: + application/json: + schema: + $ref: "#/components/schemas/listViews" + application/xml: + schema: + $ref: "#/components/schemas/listViews" + /api/v2/resources/{id}/views/{view}: + parameters: + - $ref: "#/components/parameters/id" + - $ref: "#/components/parameters/modified" + - $ref: "#/components/parameters/view" + - $ref: "#/components/parameters/accept" + - name: view + in: path + description: The ID of the view to be invoked + schema: + type: string + required: true + get: + tags: + - resources + summary: Get resource as represented by view + operationId: "r2r:getResourceView" + responses: + 200: + description: The resource in the selected representation + 404: + description: The resource or view was not found + /api/v2/resources/byPid/{pid}: + parameters: + - name: "pid" + in: path + description: The externally defined persistend ID of a file + schema: + type: string + required: true + get: + tags: + - resources + summary: Return our ID for a external PID + operationId: "r2r:getResourceByPid" + responses: + 200: + description: The internal ID for this PID + content: + text/plain: + schema: + type: string + 404: + description: This external PID was not found + + # /api/v2/search/ft/project/{ed}: + # parameters: + # - $ref: "#/components/parameters/ed" + # - $ref: "#/components/parameters/q" + # - $ref: "#/components/parameters/start" + # get: + # tags: + # - search + # summary: List files in project containing text + # operationId: #TODO + # responses: + # 200: + # $ref: "#/components/responses/files" + # 204: + # description: Search result list is empty + # 400: + # description: An error was found in the query + # 404: + # description: project not found + # /api/v2/search/ft/resource/{id}: + # parameters: + # - $ref: "#/components/parameters/id" + # - $ref: "#/components/parameters/q" + # - $ref: "#/components/parameters/start" + # get: + # tags: + # - search + # summary: List fragments in file containing text + # operationId: #TODO + # responses: + # 200: + # $ref: "#/components/responses/fragments" + # 204: + # description: Search result list is empty + # 400: + # description: An error was found in the query + # 404: + # description: File not found + + # TODO + # /api/v2/oai + + # TODO + # /api/v2/dts + +components: + securitySchemes: + cookieAuth: + type: apiKey + name: wdbplus.login + in: cookie + + parameters: + accept: + name: accept + in: header + description: Which content type should be created for this view + schema: + type: string + ed: + name: "ed" + in: path + description: The ID of the project + schema: + type: string + required: true + # entity: + # name: "entity" + # in: path + # description: The ID of the entity + # schema: + # type: string + # required: true + id: + name: "id" + in: path + description: The ID of the resource + schema: + type: string + required: true + parent: + name: "parent" + in: path + description: The ID of the parent project + schema: + type: string + required: true + # q: + # name: q + # in: query + # required: true + # schema: + # type: string + # description: query or filter by name / title + # type: + # name: type + # in: query + # description: The type of entity + # schema: + # enum: + # - per + # - pla + # - org + # - bib + # - evt + # required: true + # start: + # name: start + # in: query + # description: from which position in a list to start (1-based) + # schema: + # type: integer + # default: 1 + modified: + name: "If-Modified-Since" + in: header + schema: + type: string + format: date-time + view: + name: view + in: path + description: Which view is to be applied to a resource + schema: + type: string + required: true + + responses: + authenticate: + description: Authentication necessary + headers: + WWW-Authenticate: + description: Challenge for authentication + schema: + type: string + created: + description: Annotation, file, etc. has been created + headers: + Location: + description: Location of the annotation, file etc. + schema: + type: string + format: uri + + invalidBody: + description: Request body is invalid or not wellformed + + # annotations: + # description: A list of annotations matching the query + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/listAnnotations" + # application/xml: + # schema: + # $ref: "#/components/schemas/listAnnotations" + # fragments: + # description: A list of fragments within a file matching the query + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/listFragments" + # application/xml: + # schema: + # $ref: "#/components/schemas/listFragments" + files: + description: A list of files + content: + application/json: + schema: + $ref: "#/components/schemas/listFiles" + application/xml: + schema: + $ref: "#/components/schemas/listFiles" + + projects: + description: A list of projects + content: + application/xml: + schema: + $ref: '#/components/schemas/listProjects' + application/json: + schema: + $ref: '#/components/schemas/listProjects' + views: + description: a list of views + content: + application/xml: + schema: + $ref: "#/components/schemas/listViews" + application/json: + schema: + $ref: "#/components/schemas/listViews" + + # entities: + # description: A list of entities matching the query + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/listEntities" + # application/xml: + # schema: + # $ref: "#/components/schemas/listEntities" + # entity: + # description: A (TEI) description of one entity + # content: + # application/xml: + # schema: + # xml: + # name: entity + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # oneOf: + # - $ref: "#/components/schemas/entity-person" + # - $ref: "#/components/schemas/entity-place" + # - $ref: "#/components/schemas/entity-org" + # - $ref: "#/components/schemas/entity-bibl" + # - $ref: "#/components/schemas/entity-event" + projectContents: + description: Lists the registered contents of a project + content: + application/xml: + schema: + $ref: '#/components/schemas/contents' + application/json: + schema: + $ref: '#/components/schemas/contents' + + requestBodies: + # annotation: + # description: the full text annotation to be added + # required: true + # content: + # application/json: + # schema: + # $ref: "#/components/schemas/annotation.json" + # application/xml: + # schema: + # $ref: "#/components/schemas/annotation.xml" + project: + description: The necessary data for the project to be created or updated + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/projectMetadata" + application/xml: + schema: + $ref: "#/components/schemas/projectMetadata" + # entity: + # description: A (TEI) description of one entity + # required: true + # content: + # application/xml: + # schema: + # xml: + # name: entity + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # oneOf: + # - $ref: "#/components/schemas/entity-person" + # - $ref: "#/components/schemas/entity-place" + # - $ref: "#/components/schemas/entity-org" + # - $ref: "#/components/schemas/entity-bibl" + # - $ref: "#/components/schemas/entity-event" + # file: + # description: A full TEI file + # required: true + # content: + # application/xml: + # schema: + # $ref: "#/components/schemas/TEI" + + + schemas: + contents: + type: object + xml: + name: contents + namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + allOf: + - $ref: "#/components/schemas/listFiles" + - $ref: "#/components/schemas/listProjects" + required: + - for + login: + type: object + required: [ "user" ] + properties: + user: + description: "Name of the user" + type: string + password: + type: string + format: password + TEI: + description: A full TEI file + type: object + xml: + namespace: "http://www.tei-c.org/ns/1.0" + name: "TEI" + + # listAnnotations: + # description: A result set, containing a list of pointers to annotations + # type: object + # xml: + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # name: "result" + # properties: + # start: + # $ref: "#/components/schemas/start" + # total: + # $ref: "#/components/schemas/total" + # annotations: + # type: array + # items: + # xml: + # name: annotation + # properties: + # id: + # $ref: "#/components/schemas/id" + # listEntities: + # description: A result set, containing a list of entities + # type: object + # xml: + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # name: "result" + # properties: + # start: + # $ref: "#/components/schemas/start" + # total: + # $ref: "#/components/schemas/total" + # entities: + # type: array + # items: + # xml: + # name: entity + # properties: + # id: + # $ref: "#/components/schemas/id" + # label: + # $ref: "#/components/schemas/label" + + Result: + description: A result set, containing a list of 0+ project(s), file(s) etc. + type: object + xml: + name: list + namespace: https://github.com/dariok/wdbplus/api/schema/v1 + oneOf: + - $ref: '#/components/schemas/listProjects' + - $ref: '#/components/schemas/listViews' + ResultBase: + type: object + xml: + name: list + namespace: https://github.com/dariok/wdbplus/api/schema/v1 + properties: + start: + $ref: '#/components/schemas/attStart' + total: + $ref: '#/components/schemas/attTotal' + length: + $ref: '#/components/schemas/attLength' + level: + $ref: '#/components/schemas/attLevel' + query: + $ref: '#/components/schemas/attQuery' + for: + $ref: '#/components/schemas/attFor' + required: + - start + - total + # listFragments: + # description: A result set, containing a list of fragments within a file + # type: object + # xml: + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # name: "result" + # properties: + # start: + # $ref: "#/components/schemas/start" + # total: + # $ref: "#/components/schemas/total" + # fragment: + # $ref: "#/components/schemas/fragment" + + # fragments: + # type: array + # description: describes a fragment within a file + # items: + # xml: + # name: fragment + # properties: + # id: + # $ref: "#/components/schemas/id" + listFiles: + description: A result set, containing a list of files + allOf: + - $ref: '#/components/schemas/ResultBase' + - type: object + properties: + files: + type: array + xml: + wrapped: false + items: + $ref: "#/components/schemas/File" + File: + description: one file + type: object + xml: + name: file + properties: + id: + $ref: "#/components/schemas/attId" + label: + $ref: "#/components/schemas/attLabel" + required: + - id + - label + + listProjects: + allOf: + - $ref: '#/components/schemas/ResultBase' + - type: object + properties: + projects: + type: array + xml: + wrapped: false + items: + $ref: '#/components/schemas/Project' + Project: + description: one project + type: object + xml: + name: project + properties: + id: + $ref: '#/components/schemas/attId' + label: + $ref: '#/components/schemas/attLabel' + required: + - id + - label + + listViews: + allOf: + - $ref: '#/components/schemas/ResultBase' + - type: object + properties: + views: + type: array + xml: + wrapped: false + items: + $ref: '#/components/schemas/View' + View: + description: a view + type: object + xml: + namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + name: "view" + properties: + id: + $ref: "#/components/schemas/attId" + + projectMetadata: + description: project meta data + type: object + xml: + namespace: "https://github.com/dariok/wdbmeta" + name: project + properties: + title: + type: string + description: The Title of the project + id: + type: string + description: The ID of the project if it is to be created with a specific ID + collection: + type: string + description: The path where the project is to be created + required: + - title + - collection + + # entity-person: + # type: object + # description: describes one person + # properties: + # person: + # xml: + # namespace: "http://www.tei-c.org/ns/1.0" + # entity-place: + # type: object + # description: describes one place + # properties: + # place: + # xml: + # namespace: "http://www.tei-c.org/ns/1.0" + # entity-org: + # type: object + # description: describes one organization + # properties: + # org: + # xml: + # namespace: "http://www.tei-c.org/ns/1.0" + # entity-bibl: + # type: object + # description: describes one bibliographical entity + # properties: + # bibl: + # xml: + # namespace: "http://www.tei-c.org/ns/1.0" + # entity-event: + # type: object + # description: describes one event + # properties: + # event: + # xml: + # namespace: "http://www.tei-c.org/ns/1.0" + + # annotation.xml: + # type: object + # xml: + # namespace: "https://github.com/dariok/wdbplus/api/schema/v1" + # # example: + # # Text + # properties: + # id: + # $ref: "#/components/schemas/id" + # file: + # $ref: "#/components/schemas/file" + # createdBy: + # type: string + # xml: + # attribute: true + # createdOn: + # type: string + # format: date-time + # xml: + # attribute: true + # # text: + # # type: string + # # xml: + # # text: true + # annotation.json: + # type: object + # properties: + # id: + # $ref: "#/components/schemas/id" + # file: + # $ref: "#/components/schemas/file" + # createdBy: + # type: string + # createdOn: + # type: string + # format: date-time + # text: + # type: string + + # file: + # description: Link to a file + # type: string + # format: URI + # xml: + # attribute: true + + attId: + description: ID of this entry + type: string + format: uri + xml: + attribute: true + attFor: + description: ID of the content for which this result is produced + type: string + format: uri + xml: + attribute: true + attLabel: + description: Title to be displayed for this entry + type: string + xml: + attribute: true + attLength: + description: The length of the current page of the result set + type: integer + default: 1 + xml: + attribute: true + attLevel: + description: For which type of content is this result produced + type: string + enum: + - "global" + - "project" + - "resource" + xml: + attribute: true + attQuery: + description: the value of the query parameter passed to the endpoint + type: string + xml: + attribute: true + attStart: + description: from which position in a list the result set starts (1-based) + type: integer + default: 1 + xml: + attribute: true + attTotal: + description: total number of entries in the result set + type: integer + xml: + attribute: true diff --git a/edoc/schema/config.rng b/edoc/schema/config.rng index 9a600ac4..64267816 100644 --- a/edoc/schema/config.rng +++ b/edoc/schema/config.rng @@ -46,9 +46,14 @@ - - - + + + + + + + + diff --git a/edoc/templates/admin.html b/edoc/templates/admin.html index 0f4fefab..a430bc00 100644 --- a/edoc/templates/admin.html +++ b/edoc/templates/admin.html @@ -7,14 +7,14 @@ - <link rel="stylesheet" type="text/css" href="../resources/css/wdb.css" /> - <link rel="stylesheet" type="text/css" href="../resources/css/function.css" /> - <link rel="stylesheet" type="text/css" href="../resources/css/admin.css" /> + <link rel="stylesheet" type="text/css" href="$shared/css/wdb.css" /> + <link rel="stylesheet" type="text/css" href="$shared/css/function.css" /> + <link rel="stylesheet" type="text/css" href="$shared/css/admin.css" /> <link data-template="wdbAdmin:css" /> <script data-template="wdb:getBlob" data-template-name="jquery"></script> - <script src="../resources/scripts/js.cookie.js"></script> - <script src="../resources/scripts/function.js"></script> - <script src="../resources/scripts/admin.js"></script> + <script src="$shared/js/js.cookie.js"></script> + <script src="$shared/js/function.js"></script> + <script src="$shared/js/admin.js"></script> </head> <body> <header> diff --git a/edoc/view.html b/edoc/view.html index 7a12759e..490ae3dd 100644 --- a/edoc/view.html +++ b/edoc/view.html @@ -1,12 +1,12 @@ <!DOCTYPE html> -<html data-template="wdb:getEE"> - <head data-template="wdb:getHead"> +<html data-template="wdbv:getEE"> + <head data-template="wdbv:getHead"> <title>head set by app.xqm
-
-
+
+
-
+
-
+
- \ No newline at end of file + diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..14ab3934 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,23 @@ +module.exports = { + "env": { + "browser": true, + "es2021": true + }, + "extends": "xo", + "overrides": [ + { + "files": [ + ".eslintrc.{js,cjs}" + ], + "parserOptions": { + "sourceType": "script" + } + } + ], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + } +} diff --git a/install.xql b/install.xql deleted file mode 100644 index 591f0cfc..00000000 --- a/install.xql +++ /dev/null @@ -1,24 +0,0 @@ -xquery version "3.1"; - -import module namespace exgit="http://exist-db.org/xquery/exgit" at "java:org.exist.xquery.modules.exgit.Exgit"; - -let $whereToClone := "~/git/" - -let $cl := exgit:clone("https://github.com/dariok/wdbplus", $whereToClone) -let $ie := exgit:import($whereToClone || "/wdbplus/edoc", "/db/apps/edoc") -let $ic := exgit:import($whereToClone || "/wdbplus/config", "/db/system/config/db/apps") - -let $chmod := (sm:chmod(xs:anyURI('/db/apps/edoc/controller.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/modules/view.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-anno.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-coll.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-entity.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-files.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-search.xql'), 'r-xr-xr-x'), - sm:chmod(xs:anyURI('/db/apps/edoc/rest/rest-test.xql'), 'r-xr-xr-x') -) -let $chown := sm:chown(xs:anyURI('/db/apps/edoc/annotations'), 'wdb') -let $chgrp := sm:chgrp(xs:anyURI('/db/apps/edoc/annotations'), 'wdbusers') -let $reindex := xmldb:reindex('/db/apps/edoc/data') - -return ($cl, $ie, $ic, $chmod, $chown, $chgrp, $reindex) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e9ff5e8e..a554ed4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,530 +1,3535 @@ { "name": "wdbplus", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { - "jshint": "^2.13.5" + "jqueryui": "^1.11.1", + "xpath": "^0.0.34" }, "devDependencies": { - "@types/jquery": "^3.5.29" + "@types/jquery": "^3.5.33", + "@xmldom/xmldom": "^0.8.11", + "chai": "^6.2.2", + "chai-http": "^5.1.2", + "eslint": "^9.39.2", + "eslint-config-xo": "^0.49.0", + "jsdom": "^27.4.0", + "mocha": "^11.7.5" } }, + "node_modules/@acemir/cssom": { + "version": "0.9.31", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", + "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", + "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.0.0", + "@csstools/css-color-parser": "^4.0.1", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.2.5" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.7.8", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.8.tgz", + "integrity": "sha512-stisC1nULNc9oH5lakAj8MH88ZxeGxzyWNDfbdCxvJSJIvDsHNZqYvscGTgy/ysgXWLJPt6K/4t0/GjvtKcFJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.5" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.1.tgz", + "integrity": "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.0.tgz", + "integrity": "sha512-JWouqB5za07FUA2iXZWq4gPXNGWXjRwlfwEXNr7cSsGr7OKgzhDVwkJjlsrbqSyFmDGSi1Rt7zs8ln87jX9yRg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.1.tgz", + "integrity": "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.1", + "@csstools/css-calc": "^3.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.27", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.27.tgz", + "integrity": "sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0" + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/css": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@eslint/css/-/css-0.10.0.tgz", + "integrity": "sha512-pHoYRWS08oeU0qVez1pZCcbqHzoJnM5VMtrxH2nWDJ0ukq9DkwWV1BTY+PWK+eWBbndN9W0O9WjJTyAHsDoPOg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.14.0", + "@eslint/css-tree": "^3.6.1", + "@eslint/plugin-kit": "^0.3.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/css-tree": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@eslint/css-tree/-/css-tree-3.6.9.tgz", + "integrity": "sha512-3D5/OHibNEGk+wKwNwMbz63NMf367EoR4mVNNpxddCHKEb2Nez7z62J2U6YjtErSsZDoY0CsccmoUpdEbkogNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.23.0", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/@eslint/css/node_modules/@eslint/core": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", + "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/css/node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/css/node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/json": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@eslint/json/-/json-0.13.2.tgz", + "integrity": "sha512-yWLyRE18rHgHXhWigRpiyv1LDPkvWtC6oa7QHXW7YdP6gosJoq7BiLZW2yCs9U7zN7X4U3ZeOJjepA10XAOIMw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "@eslint/plugin-kit": "^0.3.5", + "@humanwhocodes/momoa": "^3.3.9", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/json/node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/json/node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@exodus/bytes": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.0.tgz", + "integrity": "sha512-YiY1OmY6Qhkvmly8vZiD8wZRpW/npGZNg+0Sk8mstxirRHCg6lolHt5tSODCfuNPE/fBsAqRwDJE417x7jDDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-3.3.10.tgz", + "integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.8.0.tgz", + "integrity": "sha512-WNPVF/FfBAjyi3OA7gok8swRiImNLKI4dmV3iK/GC/0xSJR7eCzBFsw9hLZVgb1+MYNLy7aDsjohxN1hA/FIfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/types": "^8.54.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/jquery": { - "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz", - "integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==", + "version": "3.5.33", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz", + "integrity": "sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.2.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", + "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.10.tgz", + "integrity": "sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/chai-http": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai-http/-/chai-http-5.1.2.tgz", + "integrity": "sha512-UFup7mUGkkjmi9bGA7F6vfp3lzGQZjtL//CEd+a4C+vlynSv756XHDUK8PoYk/UpTBBXqSghjQaJOUMUxJXNaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/superagent": "^8.1.7", + "charset": "^1.0.1", + "cookiejar": "^2.1.4", + "is-ip": "^5.0.1", + "methods": "^1.1.2", + "qs": "^6.12.1", + "superagent": "^10.0.0" + }, + "engines": { + "node": ">=18.20.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-regexp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-3.0.0.tgz", + "integrity": "sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-regexp": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-hrtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", + "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-tree/node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/cssstyle": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", + "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^4.1.1", + "@csstools/css-syntax-patches-for-csstree": "^1.0.21", + "css-tree": "^3.1.0", + "lru-cache": "^11.2.4" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/data-urls": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz", + "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^15.1.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-xo": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/eslint-config-xo/-/eslint-config-xo-0.49.0.tgz", + "integrity": "sha512-hGtD689+fdJxggx1QbEjWfgGOsTasmYqtfk3Rsxru9QyKg2iOhXO2fvR9C7ck8AGw+n2wy6FsA8/MBIzznt5/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/css": "^0.10.0", + "@eslint/json": "^0.13.1", + "@stylistic/eslint-plugin": "^5.2.3", + "confusing-browser-globals": "1.0.11", + "globals": "^16.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "peerDependencies": { + "eslint": ">=9.33.0" + } + }, + "node_modules/eslint-config-xo/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-0.1.1.tgz", + "integrity": "sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/ip-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-5.0.0.tgz", + "integrity": "sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-ip": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-5.0.1.tgz", + "integrity": "sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-regex": "^5.0.0", + "super-regex": "^0.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regexp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-3.1.0.tgz", + "integrity": "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jqueryui": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/jqueryui/-/jqueryui-1.11.1.tgz", + "integrity": "sha512-w3k80seYwcirTMG7fhd1MfqYx2dMO9fEi+I0vUN5hbX5+y7YIWySJkFsCBj4UBNuFcYOfUk6I63sUG/hCawdZA==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz", + "integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@acemir/cssom": "^0.9.28", + "@asamuzakjp/dom-selector": "^6.7.6", + "@exodus/bytes": "^1.6.0", + "cssstyle": "^5.3.4", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.0", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.23.0.tgz", + "integrity": "sha512-786vq1+4079JSeu2XdcDjrhi/Ry7BWtjDl9WtGPWLiIHb2T66GvIVflZTBoSNZ5JqTtJGYEVMuFA/lbQlMOyDQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { - "@types/sizzle": "*" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", "dependencies": { - "exit": "0.1.2", - "glob": "^7.1.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.2.5" + "node": ">=8" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", "dependencies": { - "date-now": "^0.1.4" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, - "node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", + "node_modules/super-regex": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-0.2.0.tgz", + "integrity": "sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "1" + "clone-regexp": "^3.0.0", + "function-timeout": "^0.1.0", + "time-span": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", + "node_modules/superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, + "engines": { + "node": ">=14.18.0" } }, - "node_modules/entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/time-span": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", + "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", + "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "convert-hrtime": "^5.0.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/tldts": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", + "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "tldts-core": "^7.0.23" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", + "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" }, "engines": { - "node": "*" + "node": ">=16" } }, - "node_modules/htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/jshint": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.5.tgz", - "integrity": "sha512-dB2n1w3OaQ35PLcBGIWXlszjbPZwsgZoxsg6G8PtNf2cFMC1l0fObkYLUuXqTTdi6tKw4sAjfUseTdmDMHQRcg==", - "dependencies": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "strip-json-comments": "1.0.x" + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" }, - "bin": { - "jshint": "bin/jshint" + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } }, - "node_modules/minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "node_modules/whatwg-url": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": "*" + "node": ">=20" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", "dependencies": { - "wrappy": "1" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", - "bin": { - "strip-json-comments": "cli.js" + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - }, - "dependencies": { - "@types/jquery": { - "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.29.tgz", - "integrity": "sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg==", - "dev": true, - "requires": { - "@types/sizzle": "*" + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==", - "requires": { - "date-now": "^0.1.4" + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - }, - "dependencies": { - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "utf-8-validate": { + "optional": true } } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", - "requires": { - "domelementtype": "1" + "node_modules/xpath": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", + "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", + "license": "MIT", + "engines": { + "node": ">=0.6.0" } }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" } }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" } }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "jshint": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.5.tgz", - "integrity": "sha512-dB2n1w3OaQ35PLcBGIWXlszjbPZwsgZoxsg6G8PtNf2cFMC1l0fObkYLUuXqTTdi6tKw4sAjfUseTdmDMHQRcg==", - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.21", - "minimatch": "~3.0.2", - "strip-json-comments": "1.0.x" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "minimatch": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", - "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", - "requires": { - "brace-expansion": "^1.1.7" + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 473b8db2..cc927467 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,16 @@ { "devDependencies": { - "@types/jquery": "^3.5.29" + "@types/jquery": "^3.5.33", + "@xmldom/xmldom": "^0.8.11", + "chai": "^6.2.2", + "chai-http": "^5.1.2", + "eslint": "^9.39.2", + "eslint-config-xo": "^0.49.0", + "jqueryui": "^1.11.1", + "jsdom": "^27.4.0", + "mocha": "^11.7.5", + "xpath": "^0.0.34" }, "dependencies": { - "jshint": "^2.13.5" } } diff --git a/test/entities.http b/test/entities.http index b16d5d86..eaac3423 100644 --- a/test/entities.http +++ b/test/entities.http @@ -1,5 +1,9 @@ GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/entities/list/file/pa000008-0130/person.xml +### + +GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/entities/scan/per/pa000008.xml?q=luther + ### @@ -13,8 +17,8 @@ GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/resource/pa000018-0001 ### -GET https://tueditions.ulb.tu-darmstadt.de/v/pa000018-0001 -If-Modified-Since: Thu, 15 Feb 2024 18:14:21 GMT +GET https://tueditions.ulb.tu-darmstadt.de/v/pa000018-0005 +If-Modified-Since: Fri, 23 Feb 2024 18:04:12 GMT ### diff --git a/test/mocha/r2projects.js b/test/mocha/r2projects.js new file mode 100644 index 00000000..c3d61b31 --- /dev/null +++ b/test/mocha/r2projects.js @@ -0,0 +1,807 @@ +import * as chai from "chai"; +import { default as chaiHttp, request } from "chai-http"; +import * as xmldom from "@xmldom/xmldom"; +import { JSDOM } from "jsdom"; +import * as xpath from "xpath"; +import { + baseUrl, + defaultResourcePath, + ensureSharedProject, + loginAs, + loginAsAdmin, + uniqueSuffix, + unsupportedResourceContentType, + uploadResourceMultipart +} from "./rest2-helpers.js"; + +chai.use(chaiHttp); +chai.config.includeStack = true; + +const expect = chai.expect; +const parser = new xmldom.DOMParser(); +const select = xpath.useNamespaces({ + api: "https://github.com/dariok/wdbplus/api/schema/v1", + index: "https://github.com/dariok/wdbplus/index" + }); + +const sharedProjectId = "project40"; +const sharedCollection = "test40"; + +/** + * @param {string} title + * @param {string | undefined} [xmlId] + */ +function teiXml( title, xmlId ) { + const idAttr = xmlId ? ` xml:id="${xmlId}"` : ""; + return `${title}

test

test

${title}

`; +} + +/** + * @type {string} + */ +let idCreatedByPost; + +describe("REST v2 projects", function () { + describe("OPTIONS", function () { + it("OPTIONS /projects", function ( ) { + return request.execute(baseUrl) + .options("/projects") + .then(( res ) => { + expect(res).to.have.status(200); + // TODO: adjust when roaster has been fixed + // expect(res).to.have.header("allow", "GET, POST, OPTIONS"); + expect(res.header.allow).to.include("GET"); + }); + }); + }); + + describe("GET", function () { + it("GET /projects XML", function ( ) { + return request.execute(baseUrl) + .get("/projects") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/xml"); + let doc = parser.parseFromString(res.body.toString(), "application/xml"); + expect(doc.documentElement.nodeName).to.equal("list"); + expect(doc.getElementsByTagName('project')).not.to.be.empty; + expect(doc.getElementsByTagName('project')[0].getAttribute('label')).to.equal("wdb+ main project collection"); + }); + }); + it("GET /projects JSON", function ( ) { + return request.execute(baseUrl) + .get("/projects") + .set("Accept", "application/json") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/json"); + expect(res.body).to.have.property("projects"); + expect(res.body.projects).to.be.an("array"); + expect(res.body.projects[0]).to.have.property("label", "wdb+ main project collection"); + }); + }); + }); + + describe("POST", function () { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + it("POST /projects/data/subprojects to create a new main project without ID and without login", function ( ) { + return request.execute(baseUrl) + .post("/projects/data/subprojects") + .send({ title: "test", collection: "collection" }) + .then( ( res ) => { + expect(res).to.have.status(401); + } ); + }); + it("POST /projects/data/subprojects to create without ID with login, but send an ID", function ( ) { + return agent.post("/projects/data/subprojects") + .set("Content-Type", "application/json") + .send({ + title: "New Project without ID", + short: "Created by unit test", + collection: "test10", + id: "test10" + }) + .then(( res ) => { + expect(res).to.have.status(422); + }); + }); + it("POST /projects/data/subprojects to create without ID with login, but leave out a title", function ( ) { + return agent.post("/projects/data/subprojects") + .set("Content-Type", "application/json") + .send({ + short: "Created by unit test", + collection: "test20" + }) + .then(( res ) => { + expect(res).to.have.status(422); + }); + }); + it("POST /projects/$parent/subprojects to create without ID, with login, but use a wrong parent", function () { + return agent.post("/projects/missing-parent/subprojects") + .set("Content-Type", "application/json") + .send({ + title: "Created by unit test", + collection: "test21" + }) + .then(( res ) => { + expect(res).to.have.status(404); + }); + }); + it("POST /projects/data/subprojects to create project without ID with login", function ( ) { + return agent.post("/projects/data/subprojects") + .set("Content-Type", "application/json") + .set("X-Info", "true") + .send({ + title: "New Project without ID", + short: "Created by unit test", + collection: "test30" + }) + .then(( res ) => { + idCreatedByPost = res.text; + expect(res).to.have.status(201); + }); + }); + it("POST /projects/data/subprojects to create project without ID with login, with collection that’s already in use", function ( ) { + return agent.post("/projects/data/subprojects") + .set("Content-Type", "application/json") + .set("X-Info", "true") + .send({ + title: "New Project without ID", + short: "Created by unit test", + collection: "test30" + }) + .then(( res ) => { + expect(res).to.have.status(409); + }); + }); + it("PUT /projects/data/subprojects/project to create project with ID with login", function ( ) { + return agent.put(`/projects/data/subprojects/${sharedProjectId}`) + .set("Content-Type", "application/json") + .set("X-Info", "true") + .send({ + title: "New Project with ID", + short: "Created by unit test", + collection: sharedCollection + }) + .then(( res ) => { + expect(res).to.have.status(201); + }); + }); + }); + + describe("GET by ID", function () { + it("GET /projects/data XML", function ( ) { + return request.execute(baseUrl) + .get("/projects/data") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/xml"); + + let xml = parser.parseFromString(res.body.toString(), "application/xml"); + expect(xml.documentElement.nodeName).to.equal("contents"); + expect(xml.getElementsByTagName('project')).not.to.be.empty; + + let selected = select("//api:project[@label='New Project with ID']", xml); + expect(selected).not.to.be.empty; + }); + }); + it("GET /projects/data JSON", function ( ) { + return request.execute(baseUrl) + .get("/projects/data") + .set("Accept", "application/json") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/json"); + expect(res.body).to.have.property("projects"); + expect(res.body.projects).to.be.an("array"); + let filtered = res.body.projects.filter((/** @type {{ label: string; }} */ el) => el?.label === "New Project with ID"); + expect(filtered).not.to.be.empty; + }); + }); + it("GET /projects/data/views", function ( ) { + return request.execute(baseUrl) + .get("/projects/data/views") + .set("Accept", "application/json") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res.body).to.have.property("views"); + expect(res.body.views).to.be.an("array"); + }); + }); + it("GET /projects/dat/views", function ( ) { + return request.execute(baseUrl) + .get("/projects/dat/views") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(404); + }); + }); + }); + + describe("GET subprojects", function () { + it("GET /projects/data/subprojects XML", function ( ) { + return request.execute(baseUrl) + .get("/projects/data/subprojects") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/xml"); + + let xml = parser.parseFromString(res.body.toString(), "application/xml"); + expect(xml.documentElement.nodeName).to.equal("list"); + let selected = select("//api:project[@label='New Project with ID']", xml); + expect(selected).not.to.be.empty; + }); + }); + it("GET /projects/data/subprojects JSON", function ( ) { + return request.execute(baseUrl) + .get("/projects/data/subprojects") + .set("Accept", "application/json") + .then(( res ) => { + expect(res).to.have.status(200); + expect(res).to.have.header("content-type", "application/json"); + expect(res.body).to.have.property("projects"); + expect(res.body.projects).to.be.an("array"); + let filtered = res.body.projects.filter((/** @type {{ label: string; }} */ el) => el?.label === "New Project with ID"); + expect(filtered).not.to.be.empty; + }); + }); + it("GET /projects/missing-parent/subprojects", function ( ) { + return request.execute(baseUrl) + .get("/projects/missing-parent/subprojects") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(404); + }); + }); + }); + + describe("POST project resources", function () { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + before(function () { + ensureSharedProject(agent, sharedProjectId, sharedCollection); + }); + + after(function () { + if (agent) { + agent.close(); + } + }); + + it("POST /projects/$ed/resources without login", function () { + return uploadResourceMultipart( + request.execute(baseUrl).post(`/projects/${sharedProjectId}/resources`), + defaultResourcePath, + `unauth-${uniqueSuffix()}.xml`, + teiXml("unauthorized post", "unauth-post") + ) + .then((res) => { + expect(res).to.have.status(401); + }); + }); + + it("POST /projects/$ed/resources with unsupported media type", function () { + const name = `unsupported-${uniqueSuffix()}.xml`; + const xml = teiXml("unsupported media type post"); + return agent.post(`/projects/${sharedProjectId}/resources`) + .set("Content-Type", unsupportedResourceContentType) + .send({ path: defaultResourcePath, file: { name, type: "application/xml", data: xml } }) + .then((res) => { + expect(res).to.have.status(415); + }); + }); + + it("POST /projects/$ed/resources with non-privileged user", function () { + const testAgent = request.agent(baseUrl); + return loginAs(testAgent, "test", "test") + .then(() => { + return uploadResourceMultipart( + testAgent.post(`/projects/${sharedProjectId}/resources`), + defaultResourcePath, + `forbidden-${uniqueSuffix()}.xml`, + teiXml("forbidden post") + ); + }) + .then((res) => { + expect(res).to.have.status(403); + }) + .finally(() => { + testAgent.close(); + }); + }); + + it("POST /projects/$ed/resources with a missing project", function () { + return uploadResourceMultipart( + request.execute(baseUrl).post(`/projects/missing-${uniqueSuffix()}/resources`), + defaultResourcePath, + `missing-project-${uniqueSuffix()}.xml`, + teiXml("missing project post", "missing-post") + ) + .then((res) => { + expect(res).to.have.status(404); + }); + }); + + it("POST /projects/$ed/resources with wrong payload keys", function () { + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + defaultResourcePath, + `wrong-keys-${uniqueSuffix()}.xml`, + teiXml("wrong keys"), + { id: "not-allowed" } + ) + .then((res) => { + expect(res).to.have.status(422); + }); + }); + + it("POST /projects/$ed/resources with invalid XML", function () { + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + defaultResourcePath, + `invalid-${uniqueSuffix()}.xml`, + "" + ) + .then((res) => { + expect(res).to.have.status(422); + }); + }); + + it("POST /projects/$ed/resources creates a new XML resource", function () { + const path = defaultResourcePath; + const name = `created-${uniqueSuffix()}.xml`; + const xml = teiXml("created by POST without ID"); + + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + path, + name, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + }); + }); + + it("POST /projects/$ed/resources returns 409 for duplicate xml:id", function () { + const xmlId = `duplicate-id-${uniqueSuffix()}` + , firstPath = defaultResourcePath + , firstName = `id1-${uniqueSuffix()}.xml` + , firstXml = teiXml("first duplicate id", xmlId) + , secondPath = defaultResourcePath + , secondName = `id2-${uniqueSuffix()}.xml` + , secondXml = teiXml("second duplicate id", xmlId); + + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + firstPath, + firstName, + firstXml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + secondPath, + secondName, + secondXml + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + + it("POST /projects/$ed/resources returns 409 for duplicate hash", function () { + const xml = teiXml(`hash-duplicate-${uniqueSuffix()}`); + const firstPath = defaultResourcePath; + const firstName = `hash1-${uniqueSuffix()}.xml`; + const secondPath = defaultResourcePath; + const secondName = `hash2-${uniqueSuffix()}.xml`; + + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + firstPath, + firstName, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.post(`/projects/${sharedProjectId}/resources`), + secondPath, + secondName, + xml + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + }); + + describe("PUT project resources", function () { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + before(function () { + ensureSharedProject(agent, sharedProjectId, sharedCollection); + }); + + after(function () { + if (agent) { + agent.close(); + } + }); + + it("PUT /projects/$ed/resources/$id without login", function () { + return uploadResourceMultipart( + request.execute(baseUrl).put(`/projects/${sharedProjectId}/resources/no-login-${uniqueSuffix()}`), + defaultResourcePath, + `unauth-put-${uniqueSuffix()}.xml`, + teiXml("unauthorized put") + ) + .then((res) => { + expect(res).to.have.status(401); + }); + }); + + it("PUT /projects/$ed/resources/$id with unsupported media type", function () { + const name = `unsupported-put-${uniqueSuffix()}.xml`; + const xml = teiXml("unsupported media type put"); + return agent.put(`/projects/${sharedProjectId}/resources/unsupported-${uniqueSuffix()}`) + .set("Content-Type", unsupportedResourceContentType) + .send({ path: defaultResourcePath, file: { name, type: "application/xml", data: xml } }) + .then((res) => { + expect(res).to.have.status(415); + }); + }); + + it("PUT /projects/$ed/resources/$id with non-privileged user", function () { + const testAgent = request.agent(baseUrl); + return loginAs(testAgent, "test", "test") + .then(() => { + return uploadResourceMultipart( + testAgent.put(`/projects/${sharedProjectId}/resources/forbidden-${uniqueSuffix()}`), + defaultResourcePath, + `forbidden-put-${uniqueSuffix()}.xml`, + teiXml("forbidden put") + ); + }) + .then((res) => { + expect(res).to.have.status(403); + }) + .finally(() => { + testAgent.close(); + }); + }); + + it("PUT /projects/$ed/resources/$id with wrong payload keys", function () { + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/wrong-keys-${uniqueSuffix()}`), + defaultResourcePath, + `wrong-keys-put-${uniqueSuffix()}.xml`, + teiXml("wrong keys put"), + { invalid: true } + ) + .then((res) => { + expect(res).to.have.status(422); + }); + }); + + it("PUT /projects/$ed/resources/$id with a missing project", function () { + return uploadResourceMultipart( + request.execute(baseUrl).put(`/projects/missing-${uniqueSuffix()}/resources/missing-id-${uniqueSuffix()}`), + defaultResourcePath, + `missing-project-put-${uniqueSuffix()}.xml`, + teiXml("missing project put") + ) + .then((res) => { + expect(res).to.have.status(404); + }); + }); + + it("PUT /projects/$ed/resources/$id with invalid XML", function () { + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/invalid-xml-${uniqueSuffix()}`), + defaultResourcePath, + `invalid-xml-put-${uniqueSuffix()}.xml`, + "" + ) + .then((res) => { + expect(res).to.have.status(422); + }); + }); + + it("PUT /projects/$ed/resources/$id with mismatching xml:id in content", function () { + const urlId = `url-id-${uniqueSuffix()}`; + const xmlId = `xml-id-${uniqueSuffix()}`; + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${urlId}`), + defaultResourcePath, + `mismatch-${uniqueSuffix()}.xml`, + teiXml("id mismatch", xmlId) + ) + .then((res) => { + expect(res).to.have.status(422); + }); + }); + + it("PUT /projects/$ed/resources/$id creates a new XML resource (201)", function () { + const id = `put-created-${uniqueSuffix()}`; + const path = defaultResourcePath; + const name = `created-${uniqueSuffix()}.xml`; + const xml = teiXml("put created"); + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + path, + name, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + }); + }); + + it("PUT /projects/$ed/resources/$id returns 204 for identical content", function () { + const id = `put-identical-${uniqueSuffix()}`; + const path = defaultResourcePath; + const name = `identical-${uniqueSuffix()}.xml`; + const xml = teiXml("put identical"); + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + path, + name, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + path, + name, + xml + ); + }) + .then((res) => { + expect(res).to.have.status(204); + }); + }); + + it("PUT /projects/$ed/resources/$id returns 204 for same ID/path with changed content", function () { + const id = `put-update-${uniqueSuffix()}`; + const path = defaultResourcePath; + const name = `update-${uniqueSuffix()}.xml`; + const firstXml = teiXml("put update v1"); + const secondXml = teiXml("put update v2"); + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + path, + name, + firstXml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + path, + name, + secondXml + ); + }) + .then((res) => { + expect(res).to.have.status(204); + }); + }); + + it("PUT /projects/$ed/resources/$id returns 409 for existing path with different ID", function () { + const existingId = `path-existing-${uniqueSuffix()}`; + const otherId = `path-other-${uniqueSuffix()}`; + const path = defaultResourcePath; + const name = `path-conflict-${uniqueSuffix()}.xml`; + const xml = teiXml("path conflict"); + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${existingId}`), + path, + name, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${otherId}`), + path, + name, + xml + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + + it("PUT /projects/$ed/resources/$id returns 409 for existing ID with different path", function () { + const id = `id-conflict-${uniqueSuffix()}`; + const name = `id-conflict-${uniqueSuffix()}.xml`; + const firstPath = defaultResourcePath; + const firstXml = teiXml("id conflict v1"); + const secondPath = "/texts2"; + const secondXml = teiXml("id conflict v2"); + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + firstPath, + name, + firstXml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + secondPath, + name, + secondXml + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + + it("PUT /projects/$ed/resources/$id returns 409 for existing hash with different ID and path", function () { + const id1 = `hash-existing-${uniqueSuffix()}`; + const id2 = `hash-other-${uniqueSuffix()}`; + const xml = teiXml("hash conflict put"); + const firstPath = defaultResourcePath; + const firstName = `hash-put-1-${uniqueSuffix()}.xml`; + const secondPath = "/texts2"; + const secondName = `hash-put-2-${uniqueSuffix()}.xml`; + + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id1}`), + firstPath, + firstName, + xml + ) + .then((res) => { + expect(res).to.have.status(201); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id2}`), + secondPath, + secondName, + xml + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + }); + + describe("DELETE", function () { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + it("DELETE /projects/project without login", function ( ) { + return request.execute(baseUrl) + .delete("/projects/project") + .then(( res ) => { + expect(res).to.have.status(401); + }); + }); + + it("DELETE /projects/missing-project with login", function ( ) { + return agent.post("/login") + .set("Content-Type", "multipart/form-data") + .field("user", "wdbadmin") + .field("password", "wdbadmin") + .then(( res ) => { + expect(res).to.have.status(200); + return agent.delete("/projects/missing-project") + .then(( res ) => { + expect(res).to.have.status(404); + }); + }); + }); + + it("DELETE /projects/project with login", function ( ) { + return agent.delete(`/projects/${sharedProjectId}`) + .then(( res ) => { + expect(res).to.have.status(204); + return request.execute(baseUrl) + .get(`/projects/${sharedProjectId}`) + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(404); + /* delete the project that has been created by POST above to avoid erroneous 409 */ + return agent.delete("/projects/" + idCreatedByPost) + .then(( res ) => { + expect(res).to.have.status(204); + return request.execute(baseUrl) + .get("/projects") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(200); + + let xml = parser.parseFromString(res.body.toString(), "application/xml") + , projectNodes = Array.from(xml.getElementsByTagName("project")) + , projectIds = projectNodes.map(node => node.getAttribute("id")?.split("/").at(-1)).sort(); + expect(projectIds).to.deep.equal(["data", "documentation"]); + + return request.execute(baseUrl) + .get("/projects/data/subprojects") + .set("Accept", "application/xml") + .then(( res ) => { + expect(res).to.have.status(200); + let subprojects = parser.parseFromString(res.body.toString(), "application/xml"); + expect(subprojects.documentElement.getAttribute('total')).to.equal('0'); + }); + }); + }); + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/mocha/r2resources.js b/test/mocha/r2resources.js new file mode 100644 index 00000000..a238e3c5 --- /dev/null +++ b/test/mocha/r2resources.js @@ -0,0 +1,391 @@ +import * as chai from "chai"; +import { default as chaiHttp, request } from "chai-http"; +import * as xmldom from "@xmldom/xmldom"; +import * as xpath from "xpath"; +import { + baseUrl, + defaultResourcePath, + ensureSharedProject, + loginAs, + loginAsAdmin, + uniqueSuffix, + unsupportedResourceContentType, + uploadResourceMultipart +} from "./rest2-helpers.js"; + +chai.use(chaiHttp); +chai.config.includeStack = true; + +const expect = chai.expect; +const parser = new xmldom.DOMParser(); +const select = xpath.useNamespaces({ + api: "https://github.com/dariok/wdbplus/api/schema/v1", + tei: "http://www.tei-c.org/ns/1.0", + xml: "http://www.w3.org/XML/1998/namespace" +}); + +const sharedProjectId = "resourceTextProject"; +const sharedCollection = "test50"; + +/** + * @param {string} title + * @param {string} xmlId + */ +function teiXml ( title, xmlId, bodyId = `frag-${uniqueSuffix()}` ) { + return `${title}

test

test

${title}

`; +} + +/** + * @param {ChaiHttp.Agent} agent + * @param {string} id + * @param {string} title + */ +function createProjectResource ( agent, id, title, bodyId = `frag-${uniqueSuffix()}` ) { + const name = `${id}.xml`; + const xml = teiXml(title, id, bodyId); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + defaultResourcePath, + name, + xml + ).then((res) => { + expect([201, 204]).to.include(res.status); + return { id, name, xml, bodyId }; + }); +} + +/** + * @type {{ id: string, bodyId: string }} + */ +let sharedGetResource; + +describe("REST v2 resources", function() { + describe("REST v2 resources – PUT, PATCH", function () { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent) + .then(() => ensureSharedProject(agent, sharedProjectId, sharedCollection)) + .then(() => { + const id = `resource-shared-get-${uniqueSuffix()}`; + const bodyId = `frag-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource shared get", bodyId) + .then(() => { + sharedGetResource = { id, bodyId }; + }); + }); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + it("PUT /resources/$id without login returns 401", function () { + const id = `resource-put-auth-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource put auth") + .then(() => { + return uploadResourceMultipart( + request.execute(baseUrl).put(`/resources/${id}`), + defaultResourcePath, + `${id}.xml`, + teiXml("resource put no auth", id) + ); + }) + .then((res) => { + expect(res).to.have.status(401); + }); + }); + + it("PUT /resources/$id with unsupported media type returns 415", function () { + const id = `resource-put-unsupported-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource put unsupported") + .then(() => { + return agent.put(`/resources/${id}`) + .set("Content-Type", unsupportedResourceContentType) + .send({ path: defaultResourcePath, file: { name: `${id}.xml`, type: "application/xml", data: teiXml("resource put unsupported 2", id) } }); + }) + .then((res) => { + expect(res).to.have.status(415); + }); + }); + + it("PUT /resources/$id returns 404 for missing resources", function () { + const id = `resource-put-missing-${uniqueSuffix()}`; + return uploadResourceMultipart( + agent.put(`/resources/${id}`), + defaultResourcePath, + `${id}.xml`, + teiXml("resource put missing", id) + ).then((res) => { + expect(res).to.have.status(404); + }); + }); + + it("PUT /resources/$id returns 409 for mismatching stored path", function () { + const id = `resource-put-conflict-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource put conflict") + .then(() => { + return uploadResourceMultipart( + agent.put(`/resources/${id}`), + "/other-path", + `${id}.xml`, + teiXml("resource put conflict 2", id) + ); + }) + .then((res) => { + expect(res).to.have.status(409); + }); + }); + + it("PUT /resources/$id returns 204 for identical content", function () { + const id = `resource-put-identical-${uniqueSuffix()}`; + const xml = teiXml("resource put identical", id, `frag-${uniqueSuffix()}`); + return uploadResourceMultipart( + agent.put(`/projects/${sharedProjectId}/resources/${id}`), + defaultResourcePath, + `${id}.xml`, + xml + ) + .then((res) => { + expect([201, 204]).to.include(res.status); + return uploadResourceMultipart( + agent.put(`/resources/${id}`), + defaultResourcePath, + `${id}.xml`, + xml + ); + }) + .then((res) => { + expect(res).to.have.status(204); + }); + }); + + it("PUT /resources/$id updates the stored file", function () { + const id = `resource-put-update-${uniqueSuffix()}`; + const firstBodyId = `frag-${uniqueSuffix()}`; + const secondBodyId = `frag-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource put v1", firstBodyId) + .then(() => { + return uploadResourceMultipart( + agent.put(`/resources/${id}`), + defaultResourcePath, + `${id}.xml`, + teiXml("resource put v2", id, secondBodyId) + ); + }) + .then((res) => { + expect(res).to.have.status(204); + return request.execute(baseUrl) + .get(`/resources/${id}`) + .set("Accept", "application/tei+xml"); + }) + .then((res) => { + expect(res).to.have.status(200); + const doc = parser.parseFromString(res.body.toString(), "application/xml"); + expect(select("string(//tei:div/@xml:id)", doc)).to.equal(secondBodyId); + }); + }); + + it("PATCH /resources/$id updates a fragment by xml:id", function () { + const id = `resource-patch-${uniqueSuffix()}`; + const bodyId = `frag-${uniqueSuffix()}`; + const replacement = `

patched fragment

`; + return createProjectResource(agent, id, "resource patch", bodyId) + .then(() => { + return agent.patch(`/resources/${id}`) + .set("Content-Type", "application/xml") + .send(replacement); + }) + .then((res) => { + expect(res).to.have.status(204); + return request.execute(baseUrl) + .get(`/resources/${id}`) + .set("Accept", "application/tei+xml"); + }) + .then((res) => { + const doc = parser.parseFromString(res.body.toString(), "application/xml"); + expect(select(`normalize-space(string(//tei:div[@xml:id = "${bodyId}"]/tei:p))`, doc)).to.equal("patched fragment"); + }); + }); + + it("PATCH /resources/$id returns 400 for fragments without xml:id", function () { + const id = `resource-patch-invalid-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource patch invalid") + .then(() => { + return agent.patch(`/resources/${id}`) + .set("Content-Type", "application/xml") + .send("

invalid

"); + }) + .then((res) => { + expect(res).to.have.status(400); + }); + }); + }); + + describe("REST v2 resources – GET", function() { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + if ( sharedGetResource ) { + return; + } + + agent = request.agent(baseUrl); + const id = `resource-shared-get-fallback-${uniqueSuffix()}`; + const bodyId = `frag-${uniqueSuffix()}`; + + return loginAsAdmin(agent) + .then(() => ensureSharedProject(agent, sharedProjectId, sharedCollection)) + .then(() => createProjectResource(agent, id, "resource shared get fallback", bodyId)) + .then(() => { + sharedGetResource = { id, bodyId }; + }); + }); + + after(function () { + if ( agent ) { + agent.close(); + } + }); + + it("GET /resources/$id returns 404 for missing resources", function () { + return request.execute(baseUrl) + .get(`/resources/missing-${uniqueSuffix()}`) + .set("Accept", "application/xml") + .then((res) => { + expect(res).to.have.status(404); + }); + }); + + it("GET /resources/$id returns stored TEI content", function () { + return request.execute(baseUrl) + .get(`/resources/${sharedGetResource.id}`) + .set("Accept", "application/tei+xml") + .then((res) => { + expect(res).to.have.status(200); + expect(res.header["content-type"]).to.include("application/tei+xml"); + const doc = parser.parseFromString(res.body.toString(), "application/xml"); + expect(select("string(/tei:TEI/@xml:id)", doc)).to.equal(sharedGetResource.id); + }); + }); + + it("HEAD /resources/$id returns 204 with Last-Modified", function () { + return request.execute(baseUrl).head(`/resources/${sharedGetResource.id}`) + .then((res) => { + expect(res).to.have.status(200); + expect(res).to.have.header("last-modified"); + }); + }); + + it("OPTIONS /resources/$id returns 204 with Allow", function () { + return request.execute(baseUrl).options(`/resources/${sharedGetResource.id}`) + .then((res) => { + expect(res).to.have.status(200); + expect(res).to.have.header("allow"); + expect(res.header.allow).to.include("GET"); + // TODO: adjust when roaster has been fixed + //expect(res.header.allow).to.include("PATCH"); + expect(res.header.allow).to.include("DELETE"); + }); + }); + + it("GET /resources/$id/views lists available views as XML", function () { + return request.execute(baseUrl) + .get(`/resources/${sharedGetResource.id}/views`) + .set("Accept", "application/xml") + .then((res) => { + expect(res).to.have.status(200); + const doc = parser.parseFromString(res.body.toString(), "application/xml"); + expect(doc.documentElement.nodeName).to.equal("list"); + expect(select("count(/api:list/api:view)", doc)).to.be.greaterThan(0); + }); + }); + + /* TODO: make sure the correct XSLT is selected when passing "default" or e.g. "md" and for different types + * This means we need to provide an additional XSLT and at least one non-default view and something that is not HTML + */ + it("GET /resources/$id/views/{view} resolves a listed view", function () { + let firstView; + + return request.execute(baseUrl) + .get(`/resources/${sharedGetResource.id}/views`) + .set("Accept", "application/xml") + .then((res) => { + const doc = parser.parseFromString(res.body.toString(), "application/xml"); + firstView = select("string((/api:list/api:view/@view)[1])", doc); + expect(firstView).to.be.a("string").and.not.to.equal(""); + return request.execute(baseUrl) + .get(`/resources/${sharedGetResource.id}/views/${firstView}`) + .set("Accept", "text/html"); + }) + .then((res) => { + expect(res).to.have.status(200); + }); + }); + + it("GET /resources/$id/views/{view} returns 406 for missing views", function () { + return request.execute(baseUrl) + .get(`/resources/${sharedGetResource.id}/views/missing-view-${uniqueSuffix()}`) + .set("Accept", "application/xml") + .then((res) => { + expect(res).to.have.status(406); + }); + }); + + it("GET /resources/byPid/$pid returns 404 for unknown PIDs", function () { + return request.execute(baseUrl) + .get(`/resources/byPid/uuid-${uniqueSuffix()}`) + .then((res) => { + expect(res).to.have.status(404); + }); + }); + }); + + describe("REST v2 resources – DELETE", function() { + /** + * @type {ChaiHttp.Agent} + */ + let agent; + + before(function () { + agent = request.agent(baseUrl); + return loginAsAdmin(agent) + .then(() => ensureSharedProject(agent, sharedProjectId, sharedCollection)); + }); + + after(function () { + if ( agent ) { + agent.delete("/projects/" + sharedProjectId) + .then((res) => { + console.log(res.body); + expect(res).to.have.status(204); + agent.close(); + }); + } + }); + + it("DELETE /resources/$id removes the resource", function () { + const id = `resource-delete-${uniqueSuffix()}`; + return createProjectResource(agent, id, "resource delete") + .then(() => agent.delete(`/resources/${id}`)) + .then((res) => { + expect(res).to.have.status(204); + return request.execute(baseUrl) + .get(`/resources/${id}`) + .set("Accept", "application/xml"); + }) + .then((res) => { + expect(res).to.have.status(404); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/mocha/rest2-helpers.js b/test/mocha/rest2-helpers.js new file mode 100644 index 00000000..f656fe21 --- /dev/null +++ b/test/mocha/rest2-helpers.js @@ -0,0 +1,100 @@ +import * as chai from "chai"; +import { request } from "chai-http"; + +const expect = chai.expect; + +const baseUrl = "http://localhost:8080/exist/apps/edoc/api/v2"; +const unsupportedResourceContentType = "application/json"; + +const defaultResourcePath = "/edition"; + +function uniqueSuffix() { + return `${Date.now()}-${Math.floor(Math.random() * 100000)}`; +} + +/** + * @param {import("superagent/lib/node").Request} req + * @param {string} path + * @param {string} name + * @param {string} xml + */ +function uploadResourceMultipart( req, path, name, xml, extraFields = {} ) { + req.set("Content-Type", "multipart/form-data"); + + let multipartReq = req.field("path", path); + + for ( const [key, value] of Object.entries(extraFields) ) { + multipartReq = multipartReq.field(key, String(value)); + } + + return multipartReq.attach("file", Buffer.from(String(xml), "utf8"), name); +} + +/** + * @param {ChaiHttp.Agent} agent + * @param {string} user + * @param {string} password + */ +function loginAs( agent, user, password ) { + return agent.post("/login") + .set("Content-Type", "multipart/form-data") + .field("user", user) + .field("password", password) + .then((res) => { + expect(res).to.have.status(200); + return res; + }); +} + +/** + * @param {ChaiHttp.Agent} agent + */ +function loginAsAdmin( agent ) { + return loginAs(agent, "wdbadmin", "wdbadmin"); +} + +/** + * @param {ChaiHttp.Agent} agent + * @param {string} sharedProjectId + * @param {string} sharedCollection + */ +function ensureSharedProject( agent, sharedProjectId, sharedCollection ) { + return request.execute(baseUrl) + .get(`/projects/${sharedProjectId}`) + .set("Accept", "application/xml") + .then((res) => { + if (res.status === 200) { + return res; + } + + if (res.status === 404) { + return loginAsAdmin(agent) + .then(() => { + return agent.put(`/projects/data/subprojects/${sharedProjectId}`) + .set("Content-Type", "application/json") + .send({ + title: `Shared resource tests ${sharedProjectId}`, + short: "Created by mocha", + collection: sharedCollection + }); + }) + .then((createRes) => { + expect([201, 409]).to.include(createRes.status); + return createRes; + }); + } + + throw new Error(`Unexpected status while checking shared project: ${res.status}`); + }); +} + +export { + baseUrl, + defaultResourcePath, + ensureSharedProject, + loginAs, + loginAsAdmin, + uniqueSuffix, + unsupportedResourceContentType, + uploadResourceMultipart +}; diff --git a/test/r2projects.http b/test/r2projects.http new file mode 100644 index 00000000..6dea0f51 --- /dev/null +++ b/test/r2projects.http @@ -0,0 +1,165 @@ +OPTIONS http://localhost:8080/exist/apps/edoc/api/v2/projects + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects +Accept: application/xml + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects +Accept: application/json + +### +# supposed to fail – no media type given +POST http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects + +### +# supposed to fail – POST must not have an ID +POST http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects +Content-Type: application/json + +{ + "title": "New Project", + "short": "short title", + "id": "newCollectionName" +} + +### +# supposed to fail – parent not found +POST http://localhost:8080/exist/apps/edoc/api/v2/projects/dat/subprojects +Content-Type: application/json + +{ + "title": "New Project", + "short": "short title", + "collection": "newCollectionName" +} + +### +# supposed to succeed +POST http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects +Content-Type: application/json + +{ + "title": "New Project", + "short": "short title", + "collection": "newCollectionName" +} + +### +# supposed to fail – project ID in use +PUT http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects/documentation +Content-Type: application/json + +{ + "title": "New Project", + "short": "short title", + "collection": "newCollectionName" +} + +### +# supposed to succeed +PUT http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects/project +Content-Type: application/json + +{ + "title": "New Project with ID", + "short": "Created by unit test", + "collection": "test40" +} + +### + +POST http://localhost:8080/exist/apps/edoc/api/v2/login +Content-Type: multipart/form-data; boundary=----test---- + +------test---- +Content-Disposition: form-data; name="user" + +wdbadmin +------test---- +Content-Disposition: form-data; name="password" + +wdbadmin +------test------ + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/data/views +Accept: application/json + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/data +Accept: application/xml + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/data/subprojects +Accept: application/xml + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001000/views/default +Accept: application/xml + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001740/views/start +Accept: text/html + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001740/views/navigation +Accept: text/html +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001740/resources +Accept: application/xml + +### + +DELETE http://localhost:8080/exist/apps/edoc/api/v2/projects/project + +### + +POST http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001741/resources +Content-Type: multipart/form-data; boundary=wdb + +--wdb +Content-Disposition: form-data; name="path" + +edition +--wdb +Content-Disposition: form-data; name="file"; filename="17410105.xml" +Content-Type: application/xml + +#< ../edoc/webstart.xql +< ../edoc/config.xml +#< /home/kampkaspar/git/dat/steps/50_tokenized/1741/17410105.xml +--wdb-- + +### + +PUT http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001741/resources/pb001741-0105 +Content-Type: multipart/form-data; boundary=wdb + +--wdb +Content-Disposition: form-data; name="path" + +edition/01 +--wdb +Content-Disposition: form-data; name="file"; filename="17410105.xml" +Content-Type: application/xml + +# < ../edoc/config.xml +< /home/kampkaspar/git/dat/steps/50_tokenized/1741/17410105.xml +--wdb-- + +### + +PUT http://localhost:8080/exist/apps/edoc/api/v2/projects/pb001174/resources/pb001174-0001 +Content-Type: application/xml + +< /home/kampkaspar/git/dat/steps/50_tokenized/1741/17410105.xml diff --git a/test/r2resources.http b/test/r2resources.http new file mode 100644 index 00000000..07b515ec --- /dev/null +++ b/test/r2resources.http @@ -0,0 +1,22 @@ +OPTIONS http://localhost:8080/exist/apps/edoc/api/v2/resources/resource-options-1774388081581-22273 + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/resources/resource-shared-get-fallback-1774394619113-47399/views +Accept: application/xml + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/resources/resource-shared-get-fallback-1774396208324-13301/views/md +Accept: text/html +If-Modified-Since: Wed, 25 Mar 2026 00:20:57 GMT + +### + +GET http://localhost:8080/exist/apps/edoc/api/v2/resources/resource-shared-get-fallback-1774396208324-13301 +If-Modified-Since: Wed, 25 Mar 2026 00:20:57 GMT + +### + +HEAD http://localhost:8080/exist/apps/edoc/api/v2/resources/resource-shared-get-fallback-1774396208324-13301 +If-Modified-Since: Wed, 25 Mar 2026 00:20:57 GMT diff --git a/test/rest-coll.http b/test/rest-coll.http new file mode 100644 index 00000000..a20ada70 --- /dev/null +++ b/test/rest-coll.http @@ -0,0 +1,11 @@ +GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/collection/pa000023/nav.xml + +### +GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/collection/pa000018/nav.xml + +### +GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/collection/pa000019/nav.html + +### + +GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/collection/pa000009/nav.xml \ No newline at end of file diff --git a/test/rest-files.http b/test/rest-files.http new file mode 100644 index 00000000..6fc33d31 --- /dev/null +++ b/test/rest-files.http @@ -0,0 +1,2 @@ +GET https://tueditions.localhost/r/edoc/resource/pb004030-1008/views +Accept: application/json \ No newline at end of file diff --git a/test/search.http b/test/search.http new file mode 100644 index 00000000..b45d18b9 --- /dev/null +++ b/test/search.http @@ -0,0 +1,6 @@ +GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/search/collection/jz000000.xml?q=data%20AND%20emergency + + +### + +GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/search/collection/data.xml?q=gesetz \ No newline at end of file diff --git a/wdbplus.code-workspace b/wdbplus.code-workspace index fbd804c4..772c8957 100644 --- a/wdbplus.code-workspace +++ b/wdbplus.code-workspace @@ -2,7 +2,12 @@ "folders": [ { "path": "." + }, + { + "path": "../wdbmeta" } ], - "settings": {} + "settings": { + "window.title": "${dirty}${activeEditorShort}${separator}${rootName}${separator}${profileName}${separator}${appName}" + } } diff --git a/wdbplus.xpr b/wdbplus.xpr index e3ca28f3..18aa5167 100644 --- a/wdbplus.xpr +++ b/wdbplus.xpr @@ -35,7 +35,7 @@ - edoc/rest/common.xqm + edoc/rest/ @@ -55,67 +55,7 @@ - edoc/rest/ingest.xqm - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - - - - edoc/rest/rest-files.xql - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - - - - edoc/rest/rest-coll.xql - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - - - - edoc/modules/app.xqm + edoc/modules/ @@ -153,46 +93,6 @@ - - - edoc/modules/error.xqm - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - - - - edoc/modules/function.xqm - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - edoc/config/edoc/data/collection.xconf @@ -233,26 +133,6 @@ - - - edoc/rest/rest-search.xql - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - edoc/controller.xql @@ -273,26 +153,6 @@ - - - edoc/modules/auth.xqm - - - - XQuery (ULB) - - - - - Validation_scenario - - - - - 2 - - - edoc/auth.xql @@ -375,6 +235,74 @@ + + + + + text/xquery + + + + + ${currentFileURL} + + + + + eXist-db thbw.hadw-bw.de + + + true + + + + + true + + + + + + + + + + + + + + + + text/xquery + + + + + ${currentFileURL} + + + + + <Default engine> + + + true + + + + + true + + + + + + + + + + +