2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-15 16:19:11 +00:00

commandref_modular.pl/fhemdoc_modular.js: support cross-module links (Forum #39854)

git-svn-id: https://svn.fhem.de/fhem/trunk@12027 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2016-08-21 12:05:23 +00:00
parent 3da1f2ee3f
commit 4ef2e090ff
5 changed files with 126 additions and 50 deletions

View File

@ -1333,7 +1333,7 @@ CUL_prefix($$$)
and RAWMSG for the CUL family and RAWMSG for the FHZ. and RAWMSG for the CUL family and RAWMSG for the FHZ.
</li><br> </li><br>
<li><a name="#connectCommand">connectCommand</a><br> <li><a name="connectCommand">connectCommand</a><br>
raw culfw command sent to the CUL after a (re-)connect of the USB device, raw culfw command sent to the CUL after a (re-)connect of the USB device,
and sending the usual initialization needed for the configured rfmode. and sending the usual initialization needed for the configured rfmode.
</li> </li>
@ -1643,7 +1643,7 @@ CUL_prefix($$$)
RSSI und RAWMSG f&uuml;r die CUL Familie und RAWMSG f&uuml;r FHZ. RSSI und RAWMSG f&uuml;r die CUL Familie und RAWMSG f&uuml;r FHZ.
</li><br> </li><br>
<li><a name="#connectCommand">connectCommand</a><br> <li><a name="connectCommand">connectCommand</a><br>
culfw Befehl, was nach dem Verbindungsaufbau mit dem USB-Ger&auml;t, nach culfw Befehl, was nach dem Verbindungsaufbau mit dem USB-Ger&auml;t, nach
Senden der zum Initialisieren der konfigurierten rfmode ben&ouml;tigten Senden der zum Initialisieren der konfigurierten rfmode ben&ouml;tigten
Befehle gesendet wird. Befehle gesendet wird.

View File

@ -287,7 +287,7 @@ FBAHAHTTP_Write($$$)
<li><a href="#disabledForIntervals">disabledForIntervals</a></li> <li><a href="#disabledForIntervals">disabledForIntervals</a></li>
<li><a href="#dummy">dummy</a></li> <li><a href="#dummy">dummy</a></li>
<li><a href="#fritzbox-user">fritzbox-user</a></li> <li><a href="#fritzbox-user">fritzbox-user</a></li>
<li><a name="#polltime">polltime</a><br> <li><a name="polltime">polltime</a><br>
measured in seconds, default is 300 i.e. 5 minutes measured in seconds, default is 300 i.e. 5 minutes
</li> </li>

View File

@ -5487,7 +5487,7 @@ s2Hex($)
</li> </li>
<li><a href="#do_not_notify">do_not_notify</a></li> <li><a href="#do_not_notify">do_not_notify</a></li>
<li><a href="#dummy">dummy</a></li> <li><a href="#dummy">dummy</a></li>
<li><a name="#eventForRaw">eventForRaw</a><br> <li><a name="eventForRaw">eventForRaw</a><br>
Generate an an additional event for the RAW message. Can be used if Generate an an additional event for the RAW message. Can be used if
someone fears that critical notifies wont work, if FHEM changes the event someone fears that critical notifies wont work, if FHEM changes the event
text after an update. </li> text after an update. </li>

View File

@ -5,6 +5,7 @@
use strict; use strict;
use warnings; use warnings;
my $protVersion=1;
my @lang = ("EN", "DE"); my @lang = ("EN", "DE");
my $modDir = "FHEM"; my $modDir = "FHEM";
my $now = time(); my $now = time();
@ -16,6 +17,7 @@ for my $lang (@lang) {
open(FH, $cmdref) || die("Cant open $cmdref: $!\n"); open(FH, $cmdref) || die("Cant open $cmdref: $!\n");
my $type = ""; my $type = "";
my $fileVersion = 0;
while(my $l = <FH>) { while(my $l = <FH>) {
if($l =~ m/<!-- header:(.*) -->/) { if($l =~ m/<!-- header:(.*) -->/) {
$type = $1; next; $type = $1; next;
@ -36,12 +38,24 @@ for my $lang (@lang) {
my $type = "device"; my $type = "device";
while(my $l = <FH>) { while(my $l = <FH>) {
$type = $1 if($l =~ m,<!-- header:(.*) -->,); $type = $1 if($l =~ m,<!-- header:(.*) -->,);
$fileVersion = $1 if($type && $l =~ m/<table.*protVersion='(.*)'>/);
if($l =~ m,<td class='modname'><a href='#'>(.*)</a></td><td>(.*)</td>, && if($l =~ m,<td class='modname'><a href='#'>(.*)</a></td><td>(.*)</td>, &&
!$modData{$1}) { # commandref_frame has prio !$modData{$1}{type}) { # commandref_frame has prio
$modData{$1}{type} = $type; $modData{$1}{type} = $type;
$modData{$1}{"summary$sfx"} = $2; $modData{$1}{"summary$sfx"} = $2;
$modData{$1}{ts} = $cmptime; $modData{$1}{ts} = $cmptime;
} }
if($l =~ m,<div id='modLinks'[^>]*> ([^<]+)</div>,) {
for my $ml (split(" ", $1)) {
my @kv=split(/[:,]/,$ml);
my $n = shift(@kv);
for my $v (@kv) {
$modData{$n}{modLinks}{$v} = 1;
}
}
}
} }
close(FH); close(FH);
} }
@ -51,14 +65,21 @@ for my $lang (@lang) {
next if($fName !~ m/^\d\d_(.*)\.pm$/); next if($fName !~ m/^\d\d_(.*)\.pm$/);
my $mName = $1; my $mName = $1;
my $ts = (stat("$modDir/$fName"))[9]; my $ts = (stat("$modDir/$fName"))[9];
if(!$modData{$mName} || !$modData{$mName}{ts} || $modData{$mName}{ts}<$ts) { if($protVersion != $fileVersion ||
!$modData{$mName} || !$modData{$mName}{ts} || $modData{$mName}{ts}<$ts) {
print "Checking $fName for $lang short description\n"; print "Checking $fName for $lang short description\n";
$modData{$mName}{type}="device" if(!$modData{$mName}{type}); $modData{$mName}{type}="device" if(!$modData{$mName}{type});
delete($modData{$mName}{modLinks});
open(FH, "$modDir/$fName") || die("Cant open $modDir/$fName: $!\n"); open(FH, "$modDir/$fName") || die("Cant open $modDir/$fName: $!\n");
my $ishtml;
while(my $l = <FH>) { while(my $l = <FH>) {
$ishtml = 1 if($l =~ m/^=begin\s+html/);
next if(!$ishtml);
$modData{$mName}{type}=$1 if($l =~ m/^=item\s+(helper|command|device)/); $modData{$mName}{type}=$1 if($l =~ m/^=item\s+(helper|command|device)/);
$modData{$mName}{$1} =$2 if($l =~ m/^=item\s+(summary[^ ]*)\s(.*)$/); $modData{$mName}{$1} =$2 if($l =~ m/^=item\s+(summary[^ ]*)\s(.*)$/);
$modData{$mName}{modLinks}{$1} = 1
if($l =~ m/<a\s+name=['"]([^'"]+)['"]>/ && $1 !~ m/^$mName/);
} }
close(FH); close(FH);
} }
@ -71,6 +92,7 @@ for my $lang (@lang) {
$cmdref = ">docs/commandref${sfx}.html"; $cmdref = ">docs/commandref${sfx}.html";
open(OUT, $cmdref) || die("Cant open $cmdref: $!\n"); open(OUT, $cmdref) || die("Cant open $cmdref: $!\n");
my $linkDumped = 0;
while(my $l = <IN>) { while(my $l = <IN>) {
print OUT $l; print OUT $l;
@ -82,13 +104,24 @@ EOF
} }
if($l =~ m,<!-- header:(.*) -->,) { if($l =~ m,<!-- header:(.*) -->,) {
my @mList = sort {uc($a) cmp uc($b)} keys %modData;
if(!$linkDumped) {
my $ml = "";
for my $m (@mList) {
next if(!$modData{$m}{modLinks});
$ml .= " $m:".join(",", keys(%{$modData{$m}{modLinks}}));
}
print OUT "<div id='modLinks' style='display:none'>$ml</div>\n";
$linkDumped = 1;
}
my $type = $1; my $type = $1;
while(my $l = <IN>) { while(my $l = <IN>) {
last if($l !~ m/<a href="/); last if($l !~ m/<a href="/);
} }
print OUT "<table class='block summary class_$type'>\n"; print OUT "<table class='block summary class_$type' ".
"protVersion='$protVersion'>\n";
my $rc = "odd"; my $rc = "odd";
for my $m (sort {uc($a) cmp uc($b)} keys %modData) { for my $m (@mList) {
next if(!$modData{$m}{type} || $modData{$m}{type} ne $type); next if(!$modData{$m}{type} || $modData{$m}{type} ne $type);
my $d = $modData{$m}{"summary$sfx"}; my $d = $modData{$m}{"summary$sfx"};
if(!$d) { if(!$d) {
@ -107,4 +140,6 @@ EOF
} }
} }
close(OUT);
close(IN);
} }

View File

@ -1,5 +1,5 @@
var fd_Hash={}, fd_List=[], fd_All={}, fd_AllCnt, fd_Progress=0, fd_Lang, var fd_loadedHash={}, fd_loadedList=[], fd_all={}, fd_allCnt, fd_progress=0,
fd_Offsets=[], scrolled=0; fd_lang, fd_offsets=[], fd_scrolled=0, fd_modLinks={};
function function
@ -34,13 +34,15 @@ fd_fC(fn, callback)
function function
loadOneDoc(mname, lang) loadOneDoc(mname, lang)
{ {
var origLink = mname;
function function
done(err, calc) done(err, calc)
{ {
if(fd_Progress) { if(fd_progress) {
fd_status(fd_Progress+" / "+fd_AllCnt); fd_status(fd_progress+" / "+fd_allCnt);
if(++fd_Progress > fd_AllCnt) { if(++fd_progress > fd_allCnt) {
fd_Progress = 0; fd_progress = 0;
setTimeout(calcOffsets,100); // Firefox returns wrong offsets setTimeout(calcOffsets,100); // Firefox returns wrong offsets
fd_status(""); fd_status("");
} }
@ -48,11 +50,13 @@ loadOneDoc(mname, lang)
if(calc) if(calc)
setTimeout(calcOffsets,100); setTimeout(calcOffsets,100);
if(!err) if(!err)
location.href = "#"+mname; setTimeout(function(){location.href = "#"+origLink;}, 100);
} }
} }
if(fd_Hash[mname] && fd_Hash[mname] == lang) if(fd_modLinks[mname])
mname = fd_modLinks[mname];
if(fd_loadedHash[mname] && fd_loadedHash[mname] == lang)
return done(false, false); return done(false, false);
fd_fC("help "+mname+" "+lang, function(ret){ fd_fC("help "+mname+" "+lang, function(ret){
@ -62,33 +66,53 @@ loadOneDoc(mname, lang)
ret = ret.replace(/<\/?html>/g,''); ret = ret.replace(/<\/?html>/g,'');
ret = ret.replace(/Keine deutsche Hilfe gefunden!<br\/>/,''); ret = ret.replace(/Keine deutsche Hilfe gefunden!<br\/>/,'');
ret = '<div id="FD_'+mname+'">'+ret+'</div>'; ret = '<div id="FD_'+mname+'">'+ret+'</div>';
ret = ret.replace(/target="_blank"/g, ''); // revert help URL rewrite
ret = ret.replace(/href=".*commandref.*.html#/g, 'href="#');
if(fd_Hash[mname]) if(fd_loadedHash[mname])
$("div#FD_"+mname).remove(); $("div#FD_"+mname).remove();
if(!fd_Hash[mname]) if(!fd_loadedHash[mname])
fd_List.push(mname); fd_loadedList.push(mname);
fd_Hash[mname] = lang; fd_loadedHash[mname] = lang;
fd_List.sort(); fd_loadedList.sort();
var idx=0; var idx=0;
while(fd_List[idx] != mname) while(fd_loadedList[idx] != mname)
idx++; idx++;
var toIns = "perl"; var toIns = "perl";
if(idx < fd_List.length-1) if(idx < fd_loadedList.length-1)
toIns = fd_List[idx+1]; toIns = fd_loadedList[idx+1];
$(ret).insertBefore("a[name="+toIns+"]");
console.log("insert "+mname+" before "+toIns); console.log("insert "+mname+" before "+toIns);
$(ret).insertBefore("a[name="+toIns+"]");
addAHooks("div#FD_"+mname);
return done(false, true); return done(false, true);
}); });
} }
function
addAHooks(el)
{
$(el).find("a[href]").each(function(){
var href = $(this).attr("href");
if(!href || href.indexOf("#") != 0)
return;
href = href.substr(1);
if(fd_modLinks[href] && !fd_loadedHash[href]) {
$(this).click(function(){
$("a[href=#"+href+"]").unbind('click');
loadOneDoc(href, fd_lang);
});
}
});
}
function function
calcOffsets() calcOffsets()
{ {
fd_Offsets=[]; fd_offsets=[];
for(var i1=0; i1<fd_List.length; i1++) { for(var i1=0; i1<fd_loadedList.length; i1++) {
var cr = $("a[name="+fd_List[i1]+"]").offset(); var cr = $("a[name="+fd_loadedList[i1]+"]").offset();
fd_Offsets.push(cr ? cr.top : -1); fd_offsets.push(cr ? cr.top : -1);
} }
checkScroll(); checkScroll();
} }
@ -96,25 +120,25 @@ calcOffsets()
function function
checkScroll() checkScroll()
{ {
if(!scrolled) { if(!fd_scrolled) {
setTimeout(checkScroll, 500); setTimeout(checkScroll, 500);
return; return;
} }
scrolled = 0; fd_scrolled = 0;
var viewTop=$(window).scrollTop(), viewBottom=viewTop+$(window).height(); var viewTop=$(window).scrollTop(), viewBottom=viewTop+$(window).height();
var idx=0; var idx=0;
while(idx<fd_Offsets.length) { while(idx<fd_offsets.length) {
if(fd_Offsets[idx] >= viewTop && viewBottom > fd_Offsets[idx]+30) if(fd_offsets[idx] >= viewTop && viewBottom > fd_offsets[idx]+30)
break; break;
idx++; idx++;
} }
if(idx >= fd_Offsets.length) { if(idx >= fd_offsets.length) {
$("a#otherLang").hide(); $("a#otherLang").hide();
} else { } else {
var mname = fd_List[idx]; var mname = fd_loadedList[idx];
var l1 = fd_Hash[mname], l2 = (l1=="EN" ? "DE" : "EN"); var l1 = fd_loadedHash[mname], l2 = (l1=="EN" ? "DE" : "EN");
$("a#otherLang span.mod").html(mname); $("a#otherLang span.mod").html(mname);
$("a#otherLang span[lang="+l1+"]").hide(); $("a#otherLang span[lang="+l1+"]").hide();
$("a#otherLang span[lang="+l2+"]").show(); $("a#otherLang span[lang="+l2+"]").show();
@ -126,41 +150,58 @@ function
loadOtherLang() loadOtherLang()
{ {
var mname = $("a#otherLang span.mod").html(); var mname = $("a#otherLang span.mod").html();
loadOneDoc(mname, fd_Hash[mname]=="EN" ? "DE" : "EN"); loadOneDoc(mname, fd_loadedHash[mname]=="EN" ? "DE" : "EN");
} }
$(document).ready(function(){ $(document).ready(function(){
var p = location.pathname; var p = location.pathname;
fd_Lang = p.substring(p.indexOf("commandref")+11,p.indexOf(".html")); fd_lang = p.substring(p.indexOf("commandref")+11,p.indexOf(".html"));
if(!fd_Lang || fd_Lang == '.') if(!fd_lang || fd_lang == '.')
fd_Lang = "EN"; fd_lang = "EN";
$("h3").each(function(){ fd_Hash[$(this).html()] = fd_Lang; }); $("div#modLinks").each(function(){
var a1 = $(this).html().split(" ");
for(var i1=0; i1<a1.length; i1++) {
var a2 = a1[i1].split(/[:,]/);
var mName = a2.shift();
for(var i2=0; i2<a2.length; i2++)
if(!fd_modLinks[a2[i2]])
fd_modLinks[a2[i2]] = mName;
}
});
$("a[name]").each(function(){ fd_loadedHash[$(this).attr("name")]=fd_lang; });
$("table.summary td.modname a") $("table.summary td.modname a")
.each(function(){ fd_All[$(this).html()]=1; }) .each(function(){
var mod = $(this).html();
fd_all[mod]=1;
fd_modLinks[mod] = fd_modLinks[mod+"define"] = fd_modLinks[mod+"get"] =
fd_modLinks[mod+"set"] = fd_modLinks[mod+"attribute"]= mod;
})
.click(function(e){ .click(function(e){
e.preventDefault(); e.preventDefault();
loadOneDoc($(this).html(), fd_Lang); loadOneDoc($(this).html(), fd_lang);
}); });
if(location.hash) if(location.hash)
loadOneDoc(location.hash.substr(1), fd_Lang); loadOneDoc(location.hash.substr(1), fd_lang);
$("a[name=loadAll]").show().click(function(e){ $("a[name=loadAll]").show().click(function(e){
e.preventDefault(); e.preventDefault();
$("a[name=loadAll]").hide(); $("a[name=loadAll]").hide();
location.href = "#doctop"; location.href = "#doctop";
fd_AllCnt = 0; fd_allCnt = 0;
for(var m in fd_All) fd_AllCnt++ for(var m in fd_all) fd_allCnt++
fd_Progress = 1; fd_progress = 1;
for(var mname in fd_All) for(var mname in fd_all)
loadOneDoc(mname, fd_Lang); loadOneDoc(mname, fd_lang);
}); });
$("a#otherLang").click(loadOtherLang); $("a#otherLang").click(loadOtherLang);
addAHooks("body");
window.onscroll = function(){ window.onscroll = function(){
if(!scrolled++) if(!fd_scrolled++)
setTimeout(checkScroll, 500); setTimeout(checkScroll, 500);
}; };
}); });