Module:Documentation
From KitwarePublic
Jump to navigationJump to search
Documentation for this module may be created at Module:Documentation/doc
1 -- This module implements {{documentation}}.
2
3 -- Get required modules.
4 local getArgs = require('Module:Arguments').getArgs
5 local messageBox = require('Module:Message box')
6
7 -- Get the config table.
8 local cfg = mw.loadData('Module:Documentation/config')
9
10 local p = {}
11
12 -- Often-used functions.
13 local ugsub = mw.ustring.gsub
14
15 ----------------------------------------------------------------------------
16 -- Helper functions
17 --
18 -- These are defined as local functions, but are made available in the p
19 -- table for testing purposes.
20 ----------------------------------------------------------------------------
21
22 local function message(cfgKey, valArray, expectType)
23 --[[
24 -- Gets a message from the cfg table and formats it if appropriate.
25 -- The function raises an error if the value from the cfg table is not
26 -- of the type expectType. The default type for expectType is 'string'.
27 -- If the table valArray is present, strings such as $1, $2 etc. in the
28 -- message are substituted with values from the table keys [1], [2] etc.
29 -- For example, if the message "foo-message" had the value 'Foo $2 bar $1.',
30 -- message('foo-message', {'baz', 'qux'}) would return "Foo qux bar baz."
31 --]]
32 local msg = cfg[cfgKey]
33 expectType = expectType or 'string'
34 if type(msg) ~= expectType then
35 error('message: type error in message cfg.' .. cfgKey .. ' (' .. expectType .. ' expected, got ' .. type(msg) .. ')', 2)
36 end
37 if not valArray then
38 return msg
39 end
40
41 local function getMessageVal(match)
42 match = tonumber(match)
43 return valArray[match] or error('message: no value found for key $' .. match .. ' in message cfg.' .. cfgKey, 4)
44 end
45
46 local ret = ugsub(msg, '$([1-9][0-9]*)', getMessageVal)
47 return ret
48 end
49
50 p.message = message
51
52 local function makeWikilink(page, display)
53 if display then
54 return mw.ustring.format('[[%s|%s]]', page, display)
55 else
56 return mw.ustring.format('[[%s]]', page)
57 end
58 end
59
60 p.makeWikilink = makeWikilink
61
62 local function makeCategoryLink(cat, sort)
63 local catns = mw.site.namespaces[14].name
64 return makeWikilink(catns .. ':' .. cat, sort)
65 end
66
67 p.makeCategoryLink = makeCategoryLink
68
69 local function makeUrlLink(url, display)
70 return mw.ustring.format('[%s %s]', url, display)
71 end
72
73 p.makeUrlLink = makeUrlLink
74
75 local function makeToolbar(...)
76 local ret = {}
77 local lim = select('#', ...)
78 if lim < 1 then
79 return nil
80 end
81 for i = 1, lim do
82 ret[#ret + 1] = select(i, ...)
83 end
84 return '<small style="font-style: normal;">(' .. table.concat(ret, ' | ') .. ')</small>'
85 end
86
87 p.makeToolbar = makeToolbar
88
89 ----------------------------------------------------------------------------
90 -- Argument processing
91 ----------------------------------------------------------------------------
92
93 local function makeInvokeFunc(funcName)
94 return function (frame)
95 local args = getArgs(frame, {
96 valueFunc = function (key, value)
97 if type(value) == 'string' then
98 value = value:match('^%s*(.-)%s*$') -- Remove whitespace.
99 if key == 'heading' or value ~= '' then
100 return value
101 else
102 return nil
103 end
104 else
105 return value
106 end
107 end
108 })
109 return p[funcName](args)
110 end
111 end
112
113 ----------------------------------------------------------------------------
114 -- Main function
115 ----------------------------------------------------------------------------
116
117 p.main = makeInvokeFunc('_main')
118
119 function p._main(args)
120 --[[
121 -- This function defines logic flow for the module.
122 -- @args - table of arguments passed by the user
123 --
124 -- Messages:
125 -- 'main-div-id' --> 'template-documentation'
126 -- 'main-div-classes' --> 'template-documentation iezoomfix'
127 --]]
128 local env = p.getEnvironment(args)
129 local root = mw.html.create()
130 root
131 :wikitext(p.protectionTemplate(env))
132 :wikitext(p.sandboxNotice(args, env))
133 -- This div tag is from {{documentation/start box}}, but moving it here
134 -- so that we don't have to worry about unclosed tags.
135 :tag('div')
136 :attr('id', message('main-div-id'))
137 :addClass(message('main-div-classes'))
138 :newline()
139 :wikitext(p._startBox(args, env))
140 :wikitext(p._content(args, env))
141 :tag('div')
142 :css('clear', 'both') -- So right or left floating items don't stick out of the doc box.
143 :newline()
144 :done()
145 :done()
146 :wikitext(p._endBox(args, env))
147 :wikitext(p.addTrackingCategories(env))
148 return tostring(root)
149 end
150
151 ----------------------------------------------------------------------------
152 -- Environment settings
153 ----------------------------------------------------------------------------
154
155 function p.getEnvironment(args)
156 --[[
157 -- Returns a table with information about the environment, including title objects and other namespace- or
158 -- path-related data.
159 -- @args - table of arguments passed by the user
160 --
161 -- Title objects include:
162 -- env.title - the page we are making documentation for (usually the current title)
163 -- env.templateTitle - the template (or module, file, etc.)
164 -- env.docTitle - the /doc subpage.
165 -- env.sandboxTitle - the /sandbox subpage.
166 -- env.testcasesTitle - the /testcases subpage.
167 -- env.printTitle - the print version of the template, located at the /Print subpage.
168 --
169 -- Data includes:
170 -- env.protectionLevels - the protection levels table of the title object.
171 -- env.subjectSpace - the number of the title's subject namespace.
172 -- env.docSpace - the number of the namespace the title puts its documentation in.
173 -- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.
174 -- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.
175 --
176 -- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value
177 -- returned will be nil.
178 --]]
179
180 local env, envFuncs = {}, {}
181
182 -- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value
183 -- returned by that function is memoized in the env table so that we don't call any of the functions
184 -- more than once. (Nils won't be memoized.)
185 setmetatable(env, {
186 __index = function (t, key)
187 local envFunc = envFuncs[key]
188 if envFunc then
189 local success, val = pcall(envFunc)
190 if success then
191 env[key] = val -- Memoise the value.
192 return val
193 end
194 end
195 return nil
196 end
197 })
198
199 function envFuncs.title()
200 -- The title object for the current page, or a test page passed with args.page.
201 local title
202 local titleArg = args.page
203 if titleArg then
204 title = mw.title.new(titleArg)
205 else
206 title = mw.title.getCurrentTitle()
207 end
208 return title
209 end
210
211 function envFuncs.templateTitle()
212 --[[
213 -- The template (or module, etc.) title object.
214 -- Messages:
215 -- 'sandbox-subpage' --> 'sandbox'
216 -- 'testcases-subpage' --> 'testcases'
217 --]]
218 local subjectSpace = env.subjectSpace
219 local title = env.title
220 local subpage = title.subpageText
221 if subpage == message('sandbox-subpage') or subpage == message('testcases-subpage') then
222 return mw.title.makeTitle(subjectSpace, title.baseText)
223 else
224 return mw.title.makeTitle(subjectSpace, title.text)
225 end
226 end
227
228 function envFuncs.docTitle()
229 --[[
230 -- Title object of the /doc subpage.
231 -- Messages:
232 -- 'doc-subpage' --> 'doc'
233 --]]
234 local title = env.title
235 local docname = args[1] -- User-specified doc page.
236 local docpage
237 if docname then
238 docpage = docname
239 else
240 docpage = env.docpageBase .. '/' .. message('doc-subpage')
241 end
242 return mw.title.new(docpage)
243 end
244
245 function envFuncs.sandboxTitle()
246 --[[
247 -- Title object for the /sandbox subpage.
248 -- Messages:
249 -- 'sandbox-subpage' --> 'sandbox'
250 --]]
251 return mw.title.new(env.docpageBase .. '/' .. message('sandbox-subpage'))
252 end
253
254 function envFuncs.testcasesTitle()
255 --[[
256 -- Title object for the /testcases subpage.
257 -- Messages:
258 -- 'testcases-subpage' --> 'testcases'
259 --]]
260 return mw.title.new(env.docpageBase .. '/' .. message('testcases-subpage'))
261 end
262
263 function envFuncs.printTitle()
264 --[[
265 -- Title object for the /Print subpage.
266 -- Messages:
267 -- 'print-subpage' --> 'Print'
268 --]]
269 return env.templateTitle:subPageTitle(message('print-subpage'))
270 end
271
272 function envFuncs.protectionLevels()
273 -- The protection levels table of the title object.
274 return env.title.protectionLevels
275 end
276
277 function envFuncs.subjectSpace()
278 -- The subject namespace number.
279 return mw.site.namespaces[env.title.namespace].subject.id
280 end
281
282 function envFuncs.docSpace()
283 -- The documentation namespace number. For most namespaces this is the same as the
284 -- subject namespace. However, pages in the Article, File, MediaWiki or Category
285 -- namespaces must have their /doc, /sandbox and /testcases pages in talk space.
286 local subjectSpace = env.subjectSpace
287 if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then
288 return subjectSpace + 1
289 else
290 return subjectSpace
291 end
292 end
293
294 function envFuncs.docpageBase()
295 -- The base page of the /doc, /sandbox, and /testcases subpages.
296 -- For some namespaces this is the talk page, rather than the template page.
297 local templateTitle = env.templateTitle
298 local docSpace = env.docSpace
299 local docSpaceText = mw.site.namespaces[docSpace].name
300 -- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.
301 return docSpaceText .. ':' .. templateTitle.text
302 end
303
304 function envFuncs.compareUrl()
305 -- Diff link between the sandbox and the main template using [[Special:ComparePages]].
306 local templateTitle = env.templateTitle
307 local sandboxTitle = env.sandboxTitle
308 if templateTitle.exists and sandboxTitle.exists then
309 local compareUrl = mw.uri.fullUrl(
310 'Special:ComparePages',
311 {page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}
312 )
313 return tostring(compareUrl)
314 else
315 return nil
316 end
317 end
318
319 return env
320 end
321
322 ----------------------------------------------------------------------------
323 -- Auxiliary templates
324 ----------------------------------------------------------------------------
325
326 function p.sandboxNotice(args, env)
327 --[=[
328 -- Generates a sandbox notice for display above sandbox pages.
329 -- @args - a table of arguments passed by the user
330 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
331 --
332 -- Messages:
333 -- 'sandbox-notice-image' --> '[[Image:Sandbox.svg|50px|alt=|link=]]'
334 -- 'sandbox-notice-blurb' --> 'This is the $1 for $2.'
335 -- 'sandbox-notice-diff-blurb' --> 'This is the $1 for $2 ($3).'
336 -- 'sandbox-notice-pagetype-template' --> '[[Wikipedia:Template test cases|template sandbox]] page'
337 -- 'sandbox-notice-pagetype-module' --> '[[Wikipedia:Template test cases|module sandbox]] page'
338 -- 'sandbox-notice-pagetype-other' --> 'sandbox page'
339 -- 'sandbox-notice-compare-link-display' --> 'diff'
340 -- 'sandbox-notice-testcases-blurb' --> 'See also the companion subpage for $1.'
341 -- 'sandbox-notice-testcases-link-display' --> 'test cases'
342 -- 'sandbox-category' --> 'Template sandboxes'
343 --]=]
344 local title = env.title
345 local sandboxTitle = env.sandboxTitle
346 local templateTitle = env.templateTitle
347 local subjectSpace = env.subjectSpace
348 if not (subjectSpace and title and sandboxTitle and templateTitle and mw.title.equals(title, sandboxTitle)) then
349 return nil
350 end
351 -- Build the table of arguments to pass to {{ombox}}. We need just two fields, "image" and "text".
352 local omargs = {}
353 omargs.image = message('sandbox-notice-image')
354 -- Get the text. We start with the opening blurb, which is something like
355 -- "This is the template sandbox for [[Template:Foo]] (diff)."
356 local text = ''
357 local pagetype
358 if subjectSpace == 10 then
359 pagetype = message('sandbox-notice-pagetype-template')
360 elseif subjectSpace == 828 then
361 pagetype = message('sandbox-notice-pagetype-module')
362 else
363 pagetype = message('sandbox-notice-pagetype-other')
364 end
365 local templateLink = makeWikilink(templateTitle.prefixedText)
366 local compareUrl = env.compareUrl
367 if compareUrl then
368 local compareDisplay = message('sandbox-notice-compare-link-display')
369 local compareLink = makeUrlLink(compareUrl, compareDisplay)
370 text = text .. message('sandbox-notice-diff-blurb', {pagetype, templateLink, compareLink})
371 else
372 text = text .. message('sandbox-notice-blurb', {pagetype, templateLink})
373 end
374 -- Get the test cases page blurb if the page exists. This is something like
375 -- "See also the companion subpage for [[Template:Foo/testcases|test cases]]."
376 local testcasesTitle = env.testcasesTitle
377 if testcasesTitle and testcasesTitle.exists then
378 if testcasesTitle.namespace == mw.site.namespaces.Module.id then
379 local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
380 local testcasesRunLinkDisplay = message('sandbox-notice-testcases-run-link-display')
381 local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
382 local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
383 text = text .. '<br />' .. message('sandbox-notice-testcases-run-blurb', {testcasesLink, testcasesRunLink})
384 else
385 local testcasesLinkDisplay = message('sandbox-notice-testcases-link-display')
386 local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)
387 text = text .. '<br />' .. message('sandbox-notice-testcases-blurb', {testcasesLink})
388 end
389 end
390 -- Add the sandbox to the sandbox category.
391 text = text .. makeCategoryLink(message('sandbox-category'))
392 omargs.text = text
393 local ret = '<div style="clear: both;"></div>'
394 ret = ret .. messageBox.main('ombox', omargs)
395 return ret
396 end
397
398 function p.protectionTemplate(env)
399 -- Generates the padlock icon in the top right.
400 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
401 -- Messages:
402 -- 'protection-template' --> 'pp-template'
403 -- 'protection-template-args' --> {docusage = 'yes'}
404 local protectionLevels, mProtectionBanner
405 local title = env.title
406 protectionLevels = env.protectionLevels
407 if not protectionLevels then
408 return nil
409 end
410 local editProt = protectionLevels.edit and protectionLevels.edit[1]
411 local moveProt = protectionLevels.move and protectionLevels.move[1]
412 if editProt then
413 -- The page is edit-protected.
414 mProtectionBanner = require('Module:Protection banner')
415 local reason = message('protection-reason-edit')
416 return mProtectionBanner._main{reason, small = true}
417 elseif moveProt and moveProt ~= 'autoconfirmed' then
418 -- The page is move-protected but not edit-protected. Exclude move
419 -- protection with the level "autoconfirmed", as this is equivalent to
420 -- no move protection at all.
421 mProtectionBanner = require('Module:Protection banner')
422 return mProtectionBanner._main{action = 'move', small = true}
423 else
424 return nil
425 end
426 end
427
428 ----------------------------------------------------------------------------
429 -- Start box
430 ----------------------------------------------------------------------------
431
432 p.startBox = makeInvokeFunc('_startBox')
433
434 function p._startBox(args, env)
435 --[[
436 -- This function generates the start box.
437 -- @args - a table of arguments passed by the user
438 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
439 --
440 -- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make
441 -- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox
442 -- which generate the box HTML.
443 --]]
444 env = env or p.getEnvironment(args)
445 local links
446 local content = args.content
447 if not content then
448 -- No need to include the links if the documentation is on the template page itself.
449 local linksData = p.makeStartBoxLinksData(args, env)
450 if linksData then
451 links = p.renderStartBoxLinks(linksData)
452 end
453 end
454 -- Generate the start box html.
455 local data = p.makeStartBoxData(args, env, links)
456 if data then
457 return p.renderStartBox(data)
458 else
459 -- User specified no heading.
460 return nil
461 end
462 end
463
464 function p.makeStartBoxLinksData(args, env)
465 --[[
466 -- Does initial processing of data to make the [view] [edit] [history] [purge] links.
467 -- @args - a table of arguments passed by the user
468 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
469 --
470 -- Messages:
471 -- 'view-link-display' --> 'view'
472 -- 'edit-link-display' --> 'edit'
473 -- 'history-link-display' --> 'history'
474 -- 'purge-link-display' --> 'purge'
475 -- 'file-docpage-preload' --> 'Template:Documentation/preload-filespace'
476 -- 'module-preload' --> 'Template:Documentation/preload-module-doc'
477 -- 'docpage-preload' --> 'Template:Documentation/preload'
478 -- 'create-link-display' --> 'create'
479 --]]
480 local subjectSpace = env.subjectSpace
481 local title = env.title
482 local docTitle = env.docTitle
483 if not title or not docTitle then
484 return nil
485 end
486
487 local data = {}
488 data.title = title
489 data.docTitle = docTitle
490 -- View, display, edit, and purge links if /doc exists.
491 data.viewLinkDisplay = message('view-link-display')
492 data.editLinkDisplay = message('edit-link-display')
493 data.historyLinkDisplay = message('history-link-display')
494 data.purgeLinkDisplay = message('purge-link-display')
495 -- Create link if /doc doesn't exist.
496 local preload = args.preload
497 if not preload then
498 if subjectSpace == 6 then -- File namespace
499 preload = message('file-docpage-preload')
500 elseif subjectSpace == 828 then -- Module namespace
501 preload = message('module-preload')
502 else
503 preload = message('docpage-preload')
504 end
505 end
506 data.preload = preload
507 data.createLinkDisplay = message('create-link-display')
508 return data
509 end
510
511 function p.renderStartBoxLinks(data)
512 --[[
513 -- Generates the [view][edit][history][purge] or [create] links from the data table.
514 -- @data - a table of data generated by p.makeStartBoxLinksData
515 --]]
516
517 local function escapeBrackets(s)
518 -- Escapes square brackets with HTML entities.
519 s = s:gsub('%[', '[') -- Replace square brackets with HTML entities.
520 s = s:gsub('%]', ']')
521 return s
522 end
523
524 local ret
525 local docTitle = data.docTitle
526 local title = data.title
527 if docTitle.exists then
528 local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)
529 local editLink = makeUrlLink(docTitle:fullUrl{action = 'edit'}, data.editLinkDisplay)
530 local historyLink = makeUrlLink(docTitle:fullUrl{action = 'history'}, data.historyLinkDisplay)
531 local purgeLink = makeUrlLink(title:fullUrl{action = 'purge'}, data.purgeLinkDisplay)
532 ret = '[%s] [%s] [%s] [%s]'
533 ret = escapeBrackets(ret)
534 ret = mw.ustring.format(ret, viewLink, editLink, historyLink, purgeLink)
535 else
536 local createLink = makeUrlLink(docTitle:fullUrl{action = 'edit', preload = data.preload}, data.createLinkDisplay)
537 ret = '[%s]'
538 ret = escapeBrackets(ret)
539 ret = mw.ustring.format(ret, createLink)
540 end
541 return ret
542 end
543
544 function p.makeStartBoxData(args, env, links)
545 --[=[
546 -- Does initial processing of data to pass to the start-box render function, p.renderStartBox.
547 -- @args - a table of arguments passed by the user
548 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
549 -- @links - a string containing the [view][edit][history][purge] links - could be nil if there's an error.
550 --
551 -- Messages:
552 -- 'documentation-icon-wikitext' --> '[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]'
553 -- 'template-namespace-heading' --> 'Template documentation'
554 -- 'module-namespace-heading' --> 'Module documentation'
555 -- 'file-namespace-heading' --> 'Summary'
556 -- 'other-namespaces-heading' --> 'Documentation'
557 -- 'start-box-linkclasses' --> 'mw-editsection-like plainlinks'
558 -- 'start-box-link-id' --> 'doc_editlinks'
559 -- 'testcases-create-link-display' --> 'create'
560 --]=]
561 local subjectSpace = env.subjectSpace
562 if not subjectSpace then
563 -- Default to an "other namespaces" namespace, so that we get at least some output
564 -- if an error occurs.
565 subjectSpace = 2
566 end
567 local data = {}
568
569 -- Heading
570 local heading = args.heading -- Blank values are not removed.
571 if heading == '' then
572 -- Don't display the start box if the heading arg is defined but blank.
573 return nil
574 end
575 if heading then
576 data.heading = heading
577 elseif subjectSpace == 10 then -- Template namespace
578 data.heading = message('documentation-icon-wikitext') .. ' ' .. message('template-namespace-heading')
579 elseif subjectSpace == 828 then -- Module namespace
580 data.heading = message('documentation-icon-wikitext') .. ' ' .. message('module-namespace-heading')
581 elseif subjectSpace == 6 then -- File namespace
582 data.heading = message('file-namespace-heading')
583 else
584 data.heading = message('other-namespaces-heading')
585 end
586
587 -- Heading CSS
588 local headingStyle = args['heading-style']
589 if headingStyle then
590 data.headingStyleText = headingStyle
591 elseif subjectSpace == 10 then
592 -- We are in the template or template talk namespaces.
593 data.headingFontWeight = 'bold'
594 data.headingFontSize = '125%'
595 else
596 data.headingFontSize = '150%'
597 end
598
599 -- Data for the [view][edit][history][purge] or [create] links.
600 if links then
601 data.linksClass = message('start-box-linkclasses')
602 data.linksId = message('start-box-link-id')
603 data.links = links
604 end
605
606 return data
607 end
608
609 function p.renderStartBox(data)
610 -- Renders the start box html.
611 -- @data - a table of data generated by p.makeStartBoxData.
612 local sbox = mw.html.create('div')
613 sbox
614 :css('padding-bottom', '3px')
615 :css('border-bottom', '1px solid #aaa')
616 :css('margin-bottom', '1ex')
617 :newline()
618 :tag('span')
619 :cssText(data.headingStyleText)
620 :css('font-weight', data.headingFontWeight)
621 :css('font-size', data.headingFontSize)
622 :wikitext(data.heading)
623 local links = data.links
624 if links then
625 sbox:tag('span')
626 :addClass(data.linksClass)
627 :attr('id', data.linksId)
628 :wikitext(links)
629 end
630 return tostring(sbox)
631 end
632
633 ----------------------------------------------------------------------------
634 -- Documentation content
635 ----------------------------------------------------------------------------
636
637 p.content = makeInvokeFunc('_content')
638
639 function p._content(args, env)
640 -- Displays the documentation contents
641 -- @args - a table of arguments passed by the user
642 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
643 env = env or p.getEnvironment(args)
644 local docTitle = env.docTitle
645 local content = args.content
646 if not content and docTitle and docTitle.exists then
647 content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}
648 end
649 -- The line breaks below are necessary so that "=== Headings ===" at the start and end
650 -- of docs are interpreted correctly.
651 return '\n' .. (content or '') .. '\n'
652 end
653
654 p.contentTitle = makeInvokeFunc('_contentTitle')
655
656 function p._contentTitle(args, env)
657 env = env or p.getEnvironment(args)
658 local docTitle = env.docTitle
659 if not args.content and docTitle and docTitle.exists then
660 return docTitle.prefixedText
661 else
662 return ''
663 end
664 end
665
666 ----------------------------------------------------------------------------
667 -- End box
668 ----------------------------------------------------------------------------
669
670 p.endBox = makeInvokeFunc('_endBox')
671
672 function p._endBox(args, env)
673 --[=[
674 -- This function generates the end box (also known as the link box).
675 -- @args - a table of arguments passed by the user
676 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
677 --
678 -- Messages:
679 -- 'fmbox-id' --> 'documentation-meta-data'
680 -- 'fmbox-style' --> 'background-color: #ecfcf4'
681 -- 'fmbox-textstyle' --> 'font-style: italic'
682 --
683 -- The HTML is generated by the {{fmbox}} template, courtesy of [[Module:Message box]].
684 --]=]
685
686 -- Get environment data.
687 env = env or p.getEnvironment(args)
688 local subjectSpace = env.subjectSpace
689 local docTitle = env.docTitle
690 if not subjectSpace or not docTitle then
691 return nil
692 end
693
694 -- Check whether we should output the end box at all. Add the end
695 -- box by default if the documentation exists or if we are in the
696 -- user, module or template namespaces.
697 local linkBox = args['link box']
698 if linkBox == 'off'
699 or not (
700 docTitle.exists
701 or subjectSpace == 2
702 or subjectSpace == 828
703 or subjectSpace == 10
704 )
705 then
706 return nil
707 end
708
709 -- Assemble the arguments for {{fmbox}}.
710 local fmargs = {}
711 fmargs.id = message('fmbox-id') -- Sets 'documentation-meta-data'
712 fmargs.image = 'none'
713 fmargs.style = message('fmbox-style') -- Sets 'background-color: #ecfcf4'
714 fmargs.textstyle = message('fmbox-textstyle') -- 'font-style: italic;'
715
716 -- Assemble the fmbox text field.
717 local text = ''
718 if linkBox then
719 text = text .. linkBox
720 else
721 text = text .. (p.makeDocPageBlurb(args, env) or '') -- "This documentation is transcluded from [[Foo]]."
722 if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then
723 -- We are in the user, template or module namespaces.
724 -- Add sandbox and testcases links.
725 -- "Editors can experiment in this template's sandbox and testcases pages."
726 text = text .. (p.makeExperimentBlurb(args, env) or '')
727 text = text .. '<br />'
728 if not args.content and not args[1] then
729 -- "Please add categories to the /doc subpage."
730 -- Don't show this message with inline docs or with an explicitly specified doc page,
731 -- as then it is unclear where to add the categories.
732 text = text .. (p.makeCategoriesBlurb(args, env) or '')
733 end
734 text = text .. ' ' .. (p.makeSubpagesBlurb(args, env) or '') --"Subpages of this template"
735 local printBlurb = p.makePrintBlurb(args, env) -- Two-line blurb about print versions of templates.
736 if printBlurb then
737 text = text .. '<br />' .. printBlurb
738 end
739 end
740 end
741 fmargs.text = text
742
743 return messageBox.main('fmbox', fmargs)
744 end
745
746 function p.makeDocPageBlurb(args, env)
747 --[=[
748 -- Makes the blurb "This documentation is transcluded from [[Template:Foo]] (edit, history)".
749 -- @args - a table of arguments passed by the user
750 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
751 --
752 -- Messages:
753 -- 'edit-link-display' --> 'edit'
754 -- 'history-link-display' --> 'history'
755 -- 'transcluded-from-blurb' -->
756 -- 'The above [[Wikipedia:Template documentation|documentation]]
757 -- is [[Wikipedia:Transclusion|transcluded]] from $1.'
758 -- 'module-preload' --> 'Template:Documentation/preload-module-doc'
759 -- 'create-link-display' --> 'create'
760 -- 'create-module-doc-blurb' -->
761 -- 'You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].'
762 --]=]
763 local docTitle = env.docTitle
764 if not docTitle then
765 return nil
766 end
767 local ret
768 if docTitle.exists then
769 -- /doc exists; link to it.
770 local docLink = makeWikilink(docTitle.prefixedText)
771 local editUrl = docTitle:fullUrl{action = 'edit'}
772 local editDisplay = message('edit-link-display')
773 local editLink = makeUrlLink(editUrl, editDisplay)
774 local historyUrl = docTitle:fullUrl{action = 'history'}
775 local historyDisplay = message('history-link-display')
776 local historyLink = makeUrlLink(historyUrl, historyDisplay)
777 ret = message('transcluded-from-blurb', {docLink})
778 .. ' '
779 .. makeToolbar(editLink, historyLink)
780 .. '<br />'
781 elseif env.subjectSpace == 828 then
782 -- /doc does not exist; ask to create it.
783 local createUrl = docTitle:fullUrl{action = 'edit', preload = message('module-preload')}
784 local createDisplay = message('create-link-display')
785 local createLink = makeUrlLink(createUrl, createDisplay)
786 ret = message('create-module-doc-blurb', {createLink})
787 .. '<br />'
788 end
789 return ret
790 end
791
792 function p.makeExperimentBlurb(args, env)
793 --[[
794 -- Renders the text "Editors can experiment in this template's sandbox (edit | diff) and testcases (edit) pages."
795 -- @args - a table of arguments passed by the user
796 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
797 --
798 -- Messages:
799 -- 'sandbox-link-display' --> 'sandbox'
800 -- 'sandbox-edit-link-display' --> 'edit'
801 -- 'compare-link-display' --> 'diff'
802 -- 'module-sandbox-preload' --> 'Template:Documentation/preload-module-sandbox'
803 -- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
804 -- 'sandbox-create-link-display' --> 'create'
805 -- 'mirror-edit-summary' --> 'Create sandbox version of $1'
806 -- 'mirror-link-display' --> 'mirror'
807 -- 'mirror-link-preload' --> 'Template:Documentation/mirror'
808 -- 'sandbox-link-display' --> 'sandbox'
809 -- 'testcases-link-display' --> 'testcases'
810 -- 'testcases-edit-link-display'--> 'edit'
811 -- 'template-sandbox-preload' --> 'Template:Documentation/preload-sandbox'
812 -- 'testcases-create-link-display' --> 'create'
813 -- 'testcases-link-display' --> 'testcases'
814 -- 'testcases-edit-link-display' --> 'edit'
815 -- 'module-testcases-preload' --> 'Template:Documentation/preload-module-testcases'
816 -- 'template-testcases-preload' --> 'Template:Documentation/preload-testcases'
817 -- 'experiment-blurb-module' --> 'Editors can experiment in this module's $1 and $2 pages.'
818 -- 'experiment-blurb-template' --> 'Editors can experiment in this template's $1 and $2 pages.'
819 --]]
820 local subjectSpace = env.subjectSpace
821 local templateTitle = env.templateTitle
822 local sandboxTitle = env.sandboxTitle
823 local testcasesTitle = env.testcasesTitle
824 local templatePage = templateTitle.prefixedText
825 if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then
826 return nil
827 end
828 -- Make links.
829 local sandboxLinks, testcasesLinks
830 if sandboxTitle.exists then
831 local sandboxPage = sandboxTitle.prefixedText
832 local sandboxDisplay = message('sandbox-link-display')
833 local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)
834 local sandboxEditUrl = sandboxTitle:fullUrl{action = 'edit'}
835 local sandboxEditDisplay = message('sandbox-edit-link-display')
836 local sandboxEditLink = makeUrlLink(sandboxEditUrl, sandboxEditDisplay)
837 local compareUrl = env.compareUrl
838 local compareLink
839 if compareUrl then
840 local compareDisplay = message('compare-link-display')
841 compareLink = makeUrlLink(compareUrl, compareDisplay)
842 end
843 sandboxLinks = sandboxLink .. ' ' .. makeToolbar(sandboxEditLink, compareLink)
844 else
845 local sandboxPreload
846 if subjectSpace == 828 then
847 sandboxPreload = message('module-sandbox-preload')
848 else
849 sandboxPreload = message('template-sandbox-preload')
850 end
851 local sandboxCreateUrl = sandboxTitle:fullUrl{action = 'edit', preload = sandboxPreload}
852 local sandboxCreateDisplay = message('sandbox-create-link-display')
853 local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)
854 local mirrorSummary = message('mirror-edit-summary', {makeWikilink(templatePage)})
855 local mirrorPreload = message('mirror-link-preload')
856 local mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = mirrorPreload, summary = mirrorSummary}
857 if subjectSpace == 828 then
858 mirrorUrl = sandboxTitle:fullUrl{action = 'edit', preload = templateTitle.prefixedText, summary = mirrorSummary}
859 end
860 local mirrorDisplay = message('mirror-link-display')
861 local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)
862 sandboxLinks = message('sandbox-link-display') .. ' ' .. makeToolbar(sandboxCreateLink, mirrorLink)
863 end
864 if testcasesTitle.exists then
865 local testcasesPage = testcasesTitle.prefixedText
866 local testcasesDisplay = message('testcases-link-display')
867 local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)
868 local testcasesEditUrl = testcasesTitle:fullUrl{action = 'edit'}
869 local testcasesEditDisplay = message('testcases-edit-link-display')
870 local testcasesEditLink = makeUrlLink(testcasesEditUrl, testcasesEditDisplay)
871 -- for Modules, add testcases run link if exists
872 if subjectSpace == 828 and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then
873 local testcasesRunLinkDisplay = message('testcases-run-link-display')
874 local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)
875 testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink, testcasesRunLink)
876 else
877 testcasesLinks = testcasesLink .. ' ' .. makeToolbar(testcasesEditLink)
878 end
879 else
880 local testcasesPreload
881 if subjectSpace == 828 then
882 testcasesPreload = message('module-testcases-preload')
883 else
884 testcasesPreload = message('template-testcases-preload')
885 end
886 local testcasesCreateUrl = testcasesTitle:fullUrl{action = 'edit', preload = testcasesPreload}
887 local testcasesCreateDisplay = message('testcases-create-link-display')
888 local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)
889 testcasesLinks = message('testcases-link-display') .. ' ' .. makeToolbar(testcasesCreateLink)
890 end
891 local messageName
892 if subjectSpace == 828 then
893 messageName = 'experiment-blurb-module'
894 else
895 messageName = 'experiment-blurb-template'
896 end
897 return message(messageName, {sandboxLinks, testcasesLinks})
898 end
899
900 function p.makeCategoriesBlurb(args, env)
901 --[[
902 -- Generates the text "Please add categories to the /doc subpage."
903 -- @args - a table of arguments passed by the user
904 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
905 -- Messages:
906 -- 'doc-link-display' --> '/doc'
907 -- 'add-categories-blurb' --> 'Please add categories to the $1 subpage.'
908 --]]
909 local docTitle = env.docTitle
910 if not docTitle then
911 return nil
912 end
913 local docPathLink = makeWikilink(docTitle.prefixedText, message('doc-link-display'))
914 return message('add-categories-blurb', {docPathLink})
915 end
916
917 function p.makeSubpagesBlurb(args, env)
918 --[[
919 -- Generates the "Subpages of this template" link.
920 -- @args - a table of arguments passed by the user
921 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
922
923 -- Messages:
924 -- 'template-pagetype' --> 'template'
925 -- 'module-pagetype' --> 'module'
926 -- 'default-pagetype' --> 'page'
927 -- 'subpages-link-display' --> 'Subpages of this $1'
928 --]]
929 local subjectSpace = env.subjectSpace
930 local templateTitle = env.templateTitle
931 if not subjectSpace or not templateTitle then
932 return nil
933 end
934 local pagetype
935 if subjectSpace == 10 then
936 pagetype = message('template-pagetype')
937 elseif subjectSpace == 828 then
938 pagetype = message('module-pagetype')
939 else
940 pagetype = message('default-pagetype')
941 end
942 local subpagesLink = makeWikilink(
943 'Special:PrefixIndex/' .. templateTitle.prefixedText .. '/',
944 message('subpages-link-display', {pagetype})
945 )
946 return message('subpages-blurb', {subpagesLink})
947 end
948
949 function p.makePrintBlurb(args, env)
950 --[=[
951 -- Generates the blurb displayed when there is a print version of the template available.
952 -- @args - a table of arguments passed by the user
953 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
954 --
955 -- Messages:
956 -- 'print-link-display' --> '/Print'
957 -- 'print-blurb' --> 'A [[Help:Books/for experts#Improving the book layout|print version]]'
958 -- .. ' of this template exists at $1.'
959 -- .. ' If you make a change to this template, please update the print version as well.'
960 -- 'display-print-category' --> true
961 -- 'print-category' --> 'Templates with print versions'
962 --]=]
963 local printTitle = env.printTitle
964 if not printTitle then
965 return nil
966 end
967 local ret
968 if printTitle.exists then
969 local printLink = makeWikilink(printTitle.prefixedText, message('print-link-display'))
970 ret = message('print-blurb', {printLink})
971 local displayPrintCategory = message('display-print-category', nil, 'boolean')
972 if displayPrintCategory then
973 ret = ret .. makeCategoryLink(message('print-category'))
974 end
975 end
976 return ret
977 end
978
979 ----------------------------------------------------------------------------
980 -- Tracking categories
981 ----------------------------------------------------------------------------
982
983 function p.addTrackingCategories(env)
984 --[[
985 -- Check if {{documentation}} is transcluded on a /doc or /testcases page.
986 -- @env - environment table containing title objects, etc., generated with p.getEnvironment
987
988 -- Messages:
989 -- 'display-strange-usage-category' --> true
990 -- 'doc-subpage' --> 'doc'
991 -- 'testcases-subpage' --> 'testcases'
992 -- 'strange-usage-category' --> 'Wikipedia pages with strange ((documentation)) usage'
993 --
994 -- /testcases pages in the module namespace are not categorised, as they may have
995 -- {{documentation}} transcluded automatically.
996 --]]
997 local title = env.title
998 local subjectSpace = env.subjectSpace
999 if not title or not subjectSpace then
1000 return nil
1001 end
1002 local subpage = title.subpageText
1003 local ret = ''
1004 if message('display-strange-usage-category', nil, 'boolean')
1005 and (
1006 subpage == message('doc-subpage')
1007 or subjectSpace ~= 828 and subpage == message('testcases-subpage')
1008 )
1009 then
1010 ret = ret .. makeCategoryLink(message('strange-usage-category'))
1011 end
1012 return ret
1013 end
1014
1015 return p