-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathwiki2xqdoc.xq
156 lines (146 loc) · 4.63 KB
/
wiki2xqdoc.xq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(:~
: This script creates xqdoc files from the module documentation of the BaseX Wiki.
: @author Christian Gruen, BaseX Team
:)
declare variable $BASE := 'http://docs.basex.org';
declare variable $ROOT-DIR := file:base-dir() || 'xqdoc/';
(:~
: Serializes the specified nodes. Normalizes links and newlines.
: @param $nodes nodes to be serialized
: @param $url page url
: @return string
:)
declare %private function local:serialize(
$nodes as node()*,
$url as xs:string
) as xs:string {
normalize-space(serialize(
$nodes update {
descendant-or-self::a/@href ! (
if(starts-with(., '/')) then replace value of node . with $BASE || . else
if(starts-with(., '#')) then replace value of node . with $url || .
),
delete node descendant-or-self::a/@*[name() != 'href'],
delete node descendant-or-self::br/@*
}
))
};
(:~
: Creates the xqdoc header.
: @param $xml page contents
: @param $url page url
: @return string
:)
declare %private function local:header(
$xml as node(),
$url as xs:string
) as xs:string {
'(:~ ' || out:nl() ||
' : ' || local:serialize(
$xml//div[@id = 'bodyContent']/p[not(preceding-sibling::h1)]/node(), $url
) || out:nl() ||
' :' || out:nl() ||
' : @author BaseX Team' || out:nl() ||
' : @see ' || $url || out:nl() ||
' :)'
};
(:~
: Creates namespace declarations.
: @param $uris namespace URIs
: @param $prefixes namespace prefixed
: @return string
:)
declare %private function local:namespaces(
$uris as xs:string*,
$prefixes as xs:string*
) as xs:string* {
'module namespace ' || $prefixes[1] || ' = "' || $uris[1] || '";',
for $i in 2 to count($uris)
return 'declare namespace ' || $prefixes[$i] || ' = "' || $uris[$i] || '";',
''
};
(:~
: Creates an xqdoc section for a function.
: @param $xml page contents
: @param $prefix prefix of error namespace
: @param $url page url
: @return string
:)
declare %private function local:functions(
$xml as node(),
$prefix as xs:string?,
$url as xs:string
) as xs:string* {
for $table in $xml//table[preceding::h2]
let $summary := $table/tr[td[1]/b = 'Summary']/td[2]/node()
for $signature in $table/tr[td[1]/b = 'Signatures']/td[2]/code
let $anns := (
for $param in tokenize(replace($signature/text(), '^\(|\) .*', ''), ', ')
let $tokens := tokenize($param, ' as ', 'q')
return ' : @param ' || $tokens[1] || ' value of type ' || $tokens[2],
for $return in replace($signature/text(), '^.* as ', '')[. != 'empty-sequence()']
return ' : @return value of type ' || $return,
for $error in $table/tr[td[1]/b = 'Errors']/td[2]/code
[not(preceding-sibling::node()[1] instance of text())]
let $code := $error/b ! (contains(., ':') ?? . !! ($prefix || ':' || .))
let $message := (
let $fs := $error/following-sibling::node()
let $br := ($fs/self::br)[1]
return $fs[empty($br) or . << $br]
)
return ' : @error ' || $code || ' ' ||
replace(local:serialize($message, $url), '^: ', '')
)
return (
'(:~ ' || out:nl() ||
' : ' || string-join(local:serialize($summary, $url)) || out:nl() ||
(' :' || out:nl() || string-join($anns, out:nl()) || out:nl())[exists($anns)] ||
' :)' || out:nl() ||
'declare function ' || $signature || ' external;' || out:nl()
)
};
(:~
: Creates an xqdoc page.
: @param $xml page contents
: @param $url page url
: @return string
:)
declare %private function local:page(
$xml as node(),
$url as xs:string
) as xs:string {
let $uris := $xml//code[starts-with(following-sibling::text()[1], ' namespace')]/text()
let $prefixes := $xml//code[starts-with(following-sibling::text()[1], ' prefix.')]/text()
let $error := (
for-each-pair($uris, $prefixes, function($uri, $prefix) {
if(contains($uri, 'error')) then $prefix else ()
}),
$prefixes[1]
)[1]
return string-join((
local:header($xml, $url),
local:namespaces($uris, $prefixes),
local:functions($xml, $error, $url)
), out:nl())
};
(:~
: Parses a URL and writes an xqdoc page.
: @param $xml page contents
: @param $url page url
: @return string
:)
declare %private function local:create(
$url as xs:string
) as empty-sequence() {
let $xml := html:parse(fetch:binary($BASE || $url))
let $prefix := ($xml//code[starts-with(following-sibling::text()[1], ' prefix.')]/text())[1]
let $xqdoc := local:page($xml, $url)
return file:write-text($ROOT-DIR || $prefix || '.xqm', $xqdoc)
};
file:create-dir($ROOT-DIR),
let $xml := html:parse(fetch:binary($BASE || '/wiki/Module_Library'))
for $url in $xml//td/a[@title]/@href
return (
local:create($url),
prof:sleep(50)
)