Commit 1a9bc8c6 authored by dje's avatar dje
Browse files

Premier versement du trunk. Ce dépôt remplace 'Biblissima/trunk/RXQ_viewer....

Premier versement du trunk. Ce dépôt remplace 'Biblissima/trunk/RXQ_viewer. Chaque édition/projet aura sa propre branche.
parent ded3a790
{
"directory": "ui/js/lib"
}
\ No newline at end of file
{
"name": "MaX",
"description": "Moteur d'Affichage XML",
"main": "",
"moduleType": [],
"license": "MIT",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"MathJax": "~2.5.3",
"jquery": "~2.1.4",
"jstree": "~3.2.1",
"jquery-ui": "~1.11.4",
"openseadragon": "~2.1.0",
},
"devDependencies": {
"jquery": "~2.1.4",
"MathJax": "~2.5.3",
"jstree": "~3.2.1",
"less": "~2.5.3",
"jQuery.dotdotdot": "~1.7.4",
"bootstrap": "~3.3.6"
}
}
<?xml version="1.0"?>
<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
<basexBaseURI/>
<editions>
</editions>
</configuration>
var gulp = require('gulp'),
rename = require('gulp-rename'),// Renommage des fichiers
less = require('gulp-less'),// Conversion LESS en CSS
uglify = require('gulp-uglify'); //Minification/Obfuscation des JS
//COMPILATION DES FICHIERS LESS
gulp.task('compile-less', function () {
gulp.src('./ui/css/*.less') // path to your file
.pipe(less().on('error', function(err) {
console.log(err);
}))
.pipe(gulp.dest('./ui/css/'));
});
gulp.task('compile-less-addons', function () {
gulp.src('./plugins/**/*.less') // path to your file
.pipe(less().on('error', function(err) {
console.log(err);
}))
.pipe(gulp.dest('./plugins'));
});
//MINIFICATION DES FICHIER JS
gulp.task('js-uglify', function()
{
return gulp.src('./ui/js/src/*.js') // Prend en entrée les fichiers *.js
.pipe(rename(function(path){
// Il y a différentes méthodes pour renommer les fichiers
// Voir ici pour plus d'infos : https://www.npmjs.org/package/gulp-rename
path.basename = path.basename.replace(".src", ".min");
}))
.pipe(uglify())
.pipe(gulp.dest('./ui/js/dist/'));
});
gulp.task('js-uglify-addons', function()
{
return gulp.src(//todo: auto list uiAddons and plugins js files...
[
'./plugins/correction/*.js',
'./plugins/equations/*.js',
'./plugins/pager/*.js',
'./plugins/search/*.js',
'./plugins/apparat_critique/*.js',
'./plugins/img_viewer/*.js',
'./plugins/breadcrumb/*.js',
])
.pipe(rename(function(path){
// Il y a différentes méthodes pour renommer les fichiers
// Voir ici pour plus d'infos : https://www.npmjs.org/package/gulp-rename
console.log("Minification de " + path.basename +".js")
path.basename = path.basename.replace(".src", ".min");
}))
.pipe(uglify())
.pipe(gulp.dest('./ui/js/dist/'));
});
gulp.task('watch', function(){
gulp.watch('./ui/js/src/*.js', ['js-uglify']);
gulp.watch('./ui/uiAddons/**/*.js', ['js-uglify-addons']);
gulp.watch('./plugins/**/*.js', ['js-uglify-addons']);
gulp.watch('./plugins/**/*.less', ['compile-less-addons']);
gulp.watch('./ui/css/*.less', ['compile-less']);
});
//building task
gulp.task('build',['compile-less', 'compile-less-addons', 'js-uglify','js-uglify-addons']);
gulp.task('default', ['watch']);
module namespace max = 'pddn/max';
import module namespace max.config = 'pddn/max/config' at 'rxq/config.xqm';
import module namespace max.util = 'pddn/max/util' at 'rxq/util.xqm';
import module namespace max.html = 'pddn/max/html' at 'rxq/html.xqm';
import module namespace max.route = 'pddn/max/route' at 'rxq/route.xqm';
import module namespace max.cons = 'pddn/max/cons' at 'rxq/cons.xqm';
import module namespace max.api = 'pddn/max/max_api' at 'rxq/max_api.xqm';
import module namespace request = "http://exquery.org/ns/request";
(:
declare option db:chop 'false';
:)
(:Project's home:)
declare
%rest:GET
%output:method("html")
%rest:path( "/editions/{$project}")
function max:home($project){
web:redirect(if(ends-with(request:uri(),'/')) then 'accueil' else $project || "/accueil")
};
(:gets a project's HTML page:)
declare
%rest:GET
%output:method("html")
%rest:path( "editions/{$project}/{$page=[a-zA-Z0-9_]+}")
function max:page($project, $page){
try{
switch($page)
case "parcours"
return
let $content := max.route:HTMLRouteList($project)
return max.html:wrapInHTML($project, $page, $content)
case "accueil"
(:if 'accueil' frag does not exists -> display route list by default:)
return
try{
let $content := max.html:getHTMLFragment($project,$page)
return max.html:wrapInHTML($project, $page, $content)
}
catch err:FODC0002{
let $content := max.route:HTMLRouteList($project)
return max.html:wrapInHTML($project, $page, $content)
}
default return
try{
max.html:wrapInHTML($project, $page, max.html:getHTMLFragment($project,$page))
}
catch err:FODC0002{
admin:write-log('Page/fragment "'||$page ||'" introuvable ou mal formé', 'INFO'),
<div class='error'>Page/fragment <em>{$page}</em> introuvable ou mal formé.{$err:description} - {$err:module} - {$err:line-number} </div>
}
}
catch err:config {max:max-error($err:description)}
};
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/parcours/{$routeDoc=.*\.xml|.*\.svg}")
function max:document($project,$routeDoc){
let $f:= max.route:getRouteQueryFile($project, $routeDoc)
return
if(not(file:exists($f)))
then web:redirect("../doc/" || $routeDoc)
else
max.html:wrapInHTML($project, "parcours", max.route:getRouteEntriesAsHTML($project, $routeDoc))
};
(:gets a project's XML fragment + a navigation bar(wrapped in an html skeleton):)
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/{$routeDoc=.*\.xml}/{$id}")
function max:htmlFragmentWithNavigationBar($project, $routeDoc, $id){
let $dbPath := max.config:getProjectDBPath($project)
let $xml := <div id="wrap-{$id}">{max.api:getXMLByID($dbPath, $id)}</div>
let $xsltDoc := max.util:buildXSLTDoc(
max.config:getDefaultTextXSL($project),
max.config:getXSLTAddons($project, $routeDoc))
let $xsltParams := max.config:getXSLTParams($project, $routeDoc)
return
try{
let $html := xslt:transform($xml, $xsltDoc, $xsltParams)
return max.html:wrapInHTML($project,$routeDoc, <div>{$html}</div>, $id)
}
catch *{
admin:write-log('Error [' || $err:code || '/' || $err:module || '/' || $err:line-number ||']: ' || $err:description, 'ERROR'),
max.html:wrapInHTML($project,$routeDoc,
<div class='error'>{'Error [' || $err:code || '/' || $err:module || '/' || $err:line-number ||']: ' || $err:description}</div>,$id)
}
};
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/{$routeDoc=.*\.xml}/{$id}/target/{$targetId}/{$search}")
function max:htmlFragmentAndTargetWithNavigationBar($project, $routeDoc, $id, $targetId, $search){
copy $c := max:htmlFragmentWithNavigationBar($project, $routeDoc, $id)
modify (
replace value of node $c//*[@*:id=$targetId]/@*:id with "target"
)
return ft:mark($c[.//text() contains text {$search}])
};
(:Call the check plugin method (on a specified project:)
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/checkplugins")
function max:checkPlugin($project){
let $plugins := max.config:getPluginNameList($project)
return
if(not($plugins))
then <div id='pluginsReport'>Aucun plugin pour {$project}.</div>
else
let $reports :=
<ul>{for $plugin in $plugins
return
try
{
xquery:invoke(request:uri() || "/../" || $plugin || "/report")
}
catch err:FODC0002{<div>Méthode { $plugin || "/report"} manquante.</div>}
}
</ul>
let $report :=
<div id='pluginsReport'>
<div>Installed plugin(s): {string($plugins)}</div>
{$reports}
</div>
return $report
};
(:Returns XML fragment identified by $id:)
declare
%rest:GET
%output:method("html")
%rest:path("editions/{$project}/fragment/{$id}")
function max:getXMLByID($project, $id){
max.api:getXMLByID(max.config:getProjectDBPath($project), $id)
};
(:Returns XML fragment identified by $id in its HTML version:)
declare
%rest:GET
%output:method("html")
%rest:query-param("xsl", "{$xsl}")
%rest:query-param("xslparams","{$xslparams}")
%rest:query-param("wrap", "{$wrap}")
%rest:path("editions/{$project}/fragment_html/{$id}")
function max:getHTMLByID($project, $id, $xsl, $xslparams as xs:string *, $wrap as xs:string ?)as element(){
let $xml := max.api:getXMLByID(max.config:getProjectDBPath($project), $id)
let $xsltDoc := max.util:buildXSLTDoc(
max.config:getDefaultTextXSL($project),
if($xsl) then file:parent(static-base-uri()) || string("editions/" || $project || "/ui/xsl/" || $xsl) else ()
)
let $xslrURLParams := for $param in $xslparams
let $paramName:= substring-before($param,':')
let $paramValue:= substring-after($param,':')
return map:entry($paramName,$paramValue)
(:Merge all xsl parameters: from url + project:)
let $xsltParams := map:merge((max.config:getXSLTParams($project,()),$xslrURLParams))
let $html := <div class='standalone-html' id="wrap-{$id}">
{xslt:transform($xml, $xsltDoc, $xsltParams)}
</div>
return
if($wrap and $wrap='true')
then max.html:wrapInSimpleHTML($project, $html)
else $html
};
(:returns full document. Transformed if specified in config file, or if default env. xsl exists:)
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/doc/{$doc=.*\.xml|.*\.svg}")
function max:getFullDocument($project, $doc){
let $xmlDoc := (doc(max.config:getProjectDBPath($project) || "/" || $doc)/*)[1]
return
max.html:wrapInHTML($project,"", <div id='text'>{max:transformEditionFragment($project, $xmlDoc, $doc)}</div>)
(:
catch *{
max.html:wrapInHTML($project,"", $xmlDoc,"")
}
:)
};
declare
%rest:GET
%output:method("html")
%rest:path("/editions/about")
function max:about(){
let $editions := max.config:getEditions()
let $details := <ul>{
for $ed in $editions
let $id := string($ed/@xml:id)
let $plugins := max.config:getPluginNameList($id)
let $url := $id || "/accueil"
return <li>
{$id}
<ul>
<li>Accès: <a href='{$url}'>Home page</a></li>
<li>Grammaire XML: {string($ed/@env)}</li>
<li>Plugins: {
if($plugins)
then xquery:invoke(request:uri() || "/../"||$id||"/" || "/checkplugins")
else " - "
}
<li>Parcours/Routes: {
let $type := string($ed/routeList/@type)
return
switch ($type)
case $max.cons:XQUERY_ROUTE_TYPE
return 'todo'
case $max.cons:CONFIG_LIST_ROUTE_TYPE
return string-join($ed//route/@label,', ')
case $max.cons:HTML_FILE_ROUTE_TYPE
return 'todo3'
default
return 'Par défaut (liste des documents XML de la DB)'
}</li>
</li>
</ul>
</li>
}
</ul>
return max.html:applyBindingsOnTemplate(doc("ui/templates/about.html"),
map{
'nbEditions':count($editions),
'details': $details
})
};
declare function max:transformEditionFragment($project, $xml, $route){
let $dbPath := max.config:getProjectDBPath($project)
let $xsltDoc := max.util:buildXSLTDoc(
max.config:getDefaultTextXSL($project),
max.config:getXSLTAddons($project, $route))
let $xsltParams := max.config:getXSLTParams($project, $route)
return xslt:transform($xml, $xsltDoc, $xsltParams)
};
declare
%rest:error("err:max")
%output:method("html")
%rest:error-param("description", "{$desc}")
function max:max-error($desc)
{
"Max - ERROR: " || $desc
};
{
"name": "RXQ_viewer",
"version": "0.0.0",
"description": "",
"main": "gulpfile.js",
"dependencies": {
"fs": "0.0.2",
"readline": "^1.3.0",
"xmldom": "^0.1.21"
},
"devDependencies": {
"gulp": "^3.9.0",
"gulp-less": "^3.0.5",
"gulp-rename": "^1.2.2",
"gulp-uglify": "^1.5.1",
"jstree": "^3.2.1",
"less": "^2.5.3",
"mathjax": "^2.5.1"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": ""
}
.witness_item, #witness_title{
margin-left:20px;
}
.apparat{
cursor: pointer;
}
.witness_item input{
margin-right: 5px;
}
\ No newline at end of file
var moduleApparat = new Object();
const PLUGIN_NAME="apparat";
moduleApparat['onTextChange'] = function() {
//si le fragment courant en contient pas d'apparat
if(!docWithApparat())
return;
;
//sinon
var route = (window.location.href.split("/" + MAX.getProjectID() +"/")[1]).split(".xml")[0] + ".xml";
var witnessQueryURL =
MAX.getPluginsBaseURL() + "/" + PLUGIN_NAME + "/" +
MAX.getProjectID() +"/"+route;
$.get(witnessQueryURL, function(data){
$('#options-list').append(data);
$('#txt_options').show();
});
showWitness("lem");
witnessTooltiping();
};
MAX.addModule(moduleApparat);
function showWitness(witnessClass){
$(".apparat").hide();
$("."+witnessClass).show();
}
function witnessTooltiping(){
$('[data-witnesses]').each(function(){
var wlist = $(this).attr("data-witnesses").replace(" ",", ");
$(this).attr("title", wlist);
$(this).tooltip(
{
html:true, // allows html content
content: "<div><em>Témoins:</em> "+wlist+"</div>"
}
);
});
}
function docWithApparat(){
return $(".apparat").size() > 0
}
\ No newline at end of file
module namespace max.plugin.apparat_critique = 'pddn/max/plugin/apparat_critique';
import module namespace max.config = 'pddn/max/config' at '../../rxq/config.xqm';
(:
Route witnesses list
:)
declare
%rest:GET
%output:method("html")
%rest:path("/editions/{$project}/doc/{$route=.*\.xml}/getwitnesses")
function max.plugin.apparat_critique:getRouteWitnesses($project, $route){
<ul>
{ (:todo: removes bootstrap classes (should be only added in html way):)
for $w in doc(max.config:getProjectDBPath($project) || "/" || $route)//*:listWit//*:witness[@xml:id]
let $idAsText := string($w/@xml:id)
return <li class="witness_item">
<input onchange='showWitness("{$idAsText}")'
type='radio'
name='witnesses'
class='witness'
aria-label="{$idAsText}"/><span class='witness_label'>Témoin {$idAsText}</span>
</li>
}
</ul>
};
(:
Route witnesses list
:)
declare
%rest:GET
%output:method("html")
%rest:path("/plugins/apparat/{$project}/{$route=.*\.xml}")
function max.plugin.apparat_critique:getRouteWitnessesAsHTML($project, $route)
{
<li id="witness_title" class="dropdown-header">Apparat critique</li>,
<li class="witness_item" id="lem_item">
<input onchange='showWitness("lem")'
type='radio'
name='witnesses'
class='witness'
checked="checked"
aria-label="lem"/><span class='witness_label'>Version par défaut</span>
</li>,
for $w in max.plugin.apparat_critique:getRouteWitnesses($project, $route)//li
return $w,
<li role="separator" class="divider"></li>
};
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tei="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="tei xsl">
<xsl:template match="//tei:app">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="//tei:lem">
<span>
<xsl:attribute name="class">
<xsl:if test="count(.//tei:lem)=0">
<xsl:text>lem apparat </xsl:text>
</xsl:if>
<xsl:value-of select="translate(@wit,'#','')"/>
</xsl:attribute>
<xsl:attribute name="data-witnesses">
<xsl:value-of select="translate(@wit,'#','')"/>
</xsl:attribute>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="//tei:rdg">
<span>
<xsl:attribute name="class">
<xsl:value-of select="concat(translate(@wit,'#',''),' apparat')"/>
</xsl:attribute>
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="//tei:lacunaStart | //tei:lacunaEnd">
</xsl:template>
<xsl:template match="//tei:span[contains(@class,'varLong')]">
<span>
<xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute><xsl:apply-templates/>
</span>
</xsl:template>
</xsl:stylesheet>
\ No newline at end of file
#breadcrumb{
top: 50px;
z-index:50;
margin: 0px;
min-height:20px;
font-size: 10px;
}
\ No newline at end of file
var breadcrumb = new Object();
breadcrumb['onTextChange'] = function() {
var currentPart = $("#text").find(".subpart").first().text();
console.log(currentPart);