Skip to content

Commit 4468247

Browse files
committed
Thêm bộ mô đun biểu đồ (gồm Tree Chart và Ahnentafel)
1 parent 41189b1 commit 4468247

4 files changed

Lines changed: 883 additions & 0 deletions

File tree

‎Chart/Ahnentafel/Ahnentafel.lua‎

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
--
2+
-- implements [[Template:ahnentafel]]
3+
--
4+
local p = {}
5+
-- templatestyles
6+
local templatestyles = 'Ahnentafel/styles.css'
7+
-- table of row pointers
8+
local rows = {}
9+
-- first and last indices in rows table
10+
local rowbegin, rowend = -1,-1
11+
-- tracking
12+
local tcats = ''
13+
14+
local function checkparameters(k)
15+
if (k == 'align' or k == 'collapsed' or k == 'collapsible' or
16+
k == 'title' or k == 'float' or k == 'clear' or k == 'ref' or
17+
k == 'headnotes' or k == 'headnotes_align' or
18+
k == 'footnotes' or k == 'footnotes_align' or k == 'rtl' or
19+
k == 'width' or k == 'min-width' or k == 'text-align') then
20+
return
21+
elseif (k == 'boxstyle' or k == 'style' or k == 'border') then
22+
tcats = tcats .. '[[Category:Pages using ahnentafel with ' .. k .. ']]'
23+
return
24+
elseif k:find('^boxstyle_[1-8]$') then
25+
return
26+
elseif k:find('^border_[1-8]$') then
27+
return
28+
end
29+
k = mw.ustring.gsub(k, '[^%w%-_ ]', '?')
30+
tcats = tcats .. '[[Category:Pages using ahnentafel with unknown parameters|' .. k .. ' ]]'
31+
end
32+
33+
local function addcell(r, rspan, cspan, t, s, c)
34+
if ((r + rspan - 1) < rowbegin) or (r > rowend) then
35+
-- completely out of range; do nothing
36+
return
37+
elseif r < rowbegin then
38+
-- partially out of range, adjust
39+
rspan = rspan - (rowbegin - r)
40+
r = rowbegin
41+
elseif (r + rspan - 1) > rowend then
42+
-- partially out of range, adjust
43+
rspan = rowend + 1 - r
44+
end
45+
if rspan > 0 then
46+
rows[r]:tag('td')
47+
:attr('rowspan', (rspan > 1) and rspan or nil)
48+
:attr('colspan', (cspan > 1) and cspan or nil)
49+
:cssText(s)
50+
:addClass(c)
51+
:wikitext(t)
52+
end
53+
end
54+
55+
function p.chart( frame )
56+
local getArgs = require('Module:Arguments').getArgs
57+
local args = getArgs(frame)
58+
local align = (args['align'] or ''):lower()
59+
local style = args['style'] or ''
60+
local topbranch = 'ahnentafel-t'
61+
local botbranch = 'ahnentafel-b'
62+
63+
local yesno = require('Module:Yesno')
64+
65+
if args['collapsed'] and args['collapsed'] ~= '' then
66+
args['collapsible'] = 'yes'
67+
end
68+
69+
if args['title'] and args['title'] ~= '' then
70+
args['collapsible'] = 'yes'
71+
if yesno(args['collapsed'] or 'no') then
72+
args['collapsed'] = 'yes'
73+
else
74+
args['collapsed'] = 'no'
75+
end
76+
end
77+
78+
-- style for floating
79+
if (align == 'right') then
80+
style = 'float:right;' .. style
81+
elseif (align == 'left') then
82+
style = 'float:left;' .. style
83+
elseif (align == 'center') then
84+
style = 'margin-left:auto; margin-right:auto;' .. style
85+
end
86+
87+
-- compute the number of levels and track unsupported parameters
88+
local maxnum = 0
89+
for k, v in pairs(args) do
90+
if (k and type(k) == 'number' or
91+
(type(k) == 'string' and (tonumber(k) or 0) > 0)) then
92+
if tonumber(k) > maxnum then
93+
maxnum = k
94+
end
95+
elseif (k and type(k) == 'string') then
96+
checkparameters(k)
97+
end
98+
end
99+
100+
-- limit the number of levels
101+
maxnum = (maxnum > 511) and 511 or maxnum
102+
103+
local levels = math.ceil(math.log(maxnum+1)/math.log(2))
104+
local cells = math.pow(2, levels) - 1
105+
106+
-- "fill in" missing boxes
107+
for k = cells, 2, -1 do
108+
local j = math.floor(k/2)
109+
if args[k] and args[k] ~= '' and
110+
(args[j] == nil or args[j] == '') then
111+
args[j] = ' ' -- single space
112+
end
113+
end
114+
115+
-- compute the first and last row number
116+
rowbegin = 2*cells+1
117+
rowend = 2*cells+2
118+
local cellnum = 0
119+
for l = 1,levels do
120+
local cellsk = math.pow(2,l-1)
121+
local offset = 1
122+
for k = 1,cellsk do
123+
cellnum = cellnum + 1
124+
offset = offset + 2 * (math.pow(2, levels-l + 1) - 1)
125+
if args[cellnum] and args[cellnum] ~= '' then
126+
rowbegin = (offset < rowbegin) and offset or rowbegin
127+
rowend = ((offset+1) > rowend) and (offset+1) or rowend
128+
end
129+
if args[cellnum] and args[cellnum] == '' then
130+
args[cellnum] = nil
131+
end
132+
offset = offset + 2*(math.pow(2,levels-l+1)-1) + 4
133+
end
134+
end
135+
136+
-- add a collapsing outer container if required
137+
local res = mw.html.create('')
138+
local innercell = res
139+
local innerfs = '88%'
140+
if yesno(args['collapsible'] or 'no') then
141+
local r = res:tag('table')
142+
local t = args['title'] or ('Ancestors of ' .. mw.title.getCurrentTitle().text)
143+
r:addClass('collapsible')
144+
local f = args['float'] or ''
145+
if f == 'left' then
146+
r:css('margin', '0.3em 1em 0.3em 0')
147+
r:css('float', 'left')
148+
r:css('clear', args['clear'] or 'left')
149+
r:css('min-width', args['min-width'] or args['width'] or '33em')
150+
elseif f == 'right' then
151+
r:css('margin', '0.3em 0 0.3em 1em')
152+
r:css('float', 'right')
153+
r:css('clear', args['clear'] or 'right')
154+
r:css('min-width', args['min-width'] or args['width'] or '33em')
155+
elseif align == 'center' then
156+
r:css('margin', '0.3em auto')
157+
r:css('clear', args['clear'] or 'none')
158+
r:css('min-width', args['min-width'] or args['width'] or '60em')
159+
else
160+
r:css('margin', '0.3em 0')
161+
r:css('min-width', args['min-width'] or args['width'] or '60em')
162+
end
163+
r:css('width', args['width'] or 'auto')
164+
r:css('font-size', '88%')
165+
r:css('border', '1px solid #aaa')
166+
r:tag('tr'):tag('th')
167+
:css('padding', '0.2em 0.3em 0.2em 4.3em')
168+
:css('background', 'none')
169+
:css('color', 'inherit')
170+
:css('width', args['width'] or 'auto')
171+
:wikitext(t .. (args['ref'] or ''))
172+
innercell = r:tag('tr'):tag('td')
173+
:css('text-align', args['text-align'] or 'center')
174+
innerfs = nil
175+
args['ref'] = nil
176+
end
177+
178+
-- add content before the table if required
179+
if args['headnotes'] then
180+
if args['headnotes_align'] then
181+
innercell:tag('div')
182+
:css('width','100%')
183+
:css('text-align',args['headnotes_align'])
184+
:wikitext(args['headnotes'])
185+
else
186+
innercell:wikitext(args['headnotes'])
187+
end
188+
end
189+
190+
-- build the inner table
191+
local root = innercell:tag('table')
192+
root:addClass('ahnentafel')
193+
:css('font-size', innerfs)
194+
:cssText(style)
195+
196+
-- initialize the rows with 1 by 1 blank cells
197+
for k = rowbegin, (rowend+1) do
198+
rows[k] = root:tag('tr')
199+
rows[k]:tag('td'):wikitext(' ')
200+
end
201+
-- add a blank row of cells to assist with alignment
202+
for k = 1,(3*levels + 1) do
203+
rows[rowend+1]:tag('td'):wikitext(' ')
204+
end
205+
206+
local cellnum = 0
207+
for l = 1,levels do
208+
local levelstyle = args['boxstyle_' .. l] or ''
209+
if args['boxstyle'] and args['boxstyle'] ~= '' then
210+
levelstyle = args['boxstyle'] .. ';' .. levelstyle
211+
end
212+
levelstyle = 'height:0.5em; padding: 2px 4px 2px 4px;' .. levelstyle
213+
levelstyle = 'border:' .. (args['border_' .. l] or args['border'] or '1') .. 'px solid black;' .. levelstyle
214+
215+
local cellsk = math.pow(2,l-1)
216+
local offset = 1
217+
for k = 1,cellsk do
218+
cellnum = cellnum + 1
219+
-- top padding
220+
addcell(offset, 2*(math.pow(2,levels-l+1)-1), (l < levels) and 2 or 4, ' ', nil, nil)
221+
-- top branch
222+
if l < levels then
223+
addcell(offset, math.pow(2,levels-l+1)-1, 1, ' ', nil, nil)
224+
addcell(offset + math.pow(2,levels-l+1)-1, math.pow(2,levels-l+1)-1, 1, ' ', nil,
225+
args[2*cellnum] and topbranch or nil)
226+
end
227+
offset = offset + 2*(math.pow(2,levels-l+1)-1)
228+
-- cell
229+
addcell(offset, 2, 4, args[cellnum] or ' ', args[cellnum] and levelstyle or nil, nil)
230+
if l < levels then
231+
addcell(offset, 2, 3 + 4*(levels - l - 1), ' ', nil, nil)
232+
end
233+
offset = offset + 2
234+
-- bottom padding
235+
addcell(offset, 2*(math.pow(2,levels-l+1)-1), (l < levels) and 2 or 4, ' ', nil, nil)
236+
-- bottom branch
237+
if l < levels then
238+
addcell(offset, math.pow(2,levels-l+1)-1, 1, ' ', nil,
239+
args[2*cellnum+1] and botbranch or nil)
240+
addcell(offset + math.pow(2,levels-l+1)-1, math.pow(2,levels-l+1)-1, 1, ' ', nil, nil)
241+
end
242+
offset = offset + 2*(math.pow(2,levels-l+1)-1) + 2
243+
end
244+
end
245+
246+
-- add content after the table if required
247+
if args['footnotes'] or args['ref'] then
248+
if args['footnotes_align'] then
249+
innercell:tag('div')
250+
:css('width','100%')
251+
:css('text-align',args['footnotes_align'])
252+
:wikitext(args['footnotes'])
253+
else
254+
innercell:wikitext(args['ref'])
255+
innercell:wikitext(args['footnotes'])
256+
end
257+
end
258+
259+
return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} }
260+
.. '<div class="noresize">' .. tostring(res) .. '</div>' .. tcats
261+
end
262+
263+
return p

‎Chart/Ahnentafel/styles.css‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
table.ahnentafel {
2+
border-collapse: separate;
3+
border-spacing: 0;
4+
line-height: 130%;
5+
}
6+
.ahnentafel tr {
7+
text-align:center;
8+
}
9+
.ahnentafel-t {
10+
border-top:var(--color-base, #000) solid 1px;
11+
border-left:var(--color-base, #000) solid 1px;
12+
}
13+
.ahnentafel-b {
14+
border-bottom:var(--color-base, #000) solid 1px;
15+
border-left:var(--color-base, #000) solid 1px;
16+
}

0 commit comments

Comments
 (0)