Jump to content
Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
If you make an edit, a temporary account will be created for you.

Editing Module:Feedback

From The Petit Planet Wiki
Warning: You are not logged in. Once you make an edit, a temporary account will be created for you. Learn more. Log in or create an account to continue receiving notifications after this account expires, and to access other features.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 2: Line 2:


------------------------------------------------------------
------------------------------------------------------------
-- HELPERS
-- Helpers
------------------------------------------------------------
------------------------------------------------------------


local function isTruthy(value)
local function isTruthy(v)
if value == nil then
if v == nil then
return false
return false
end
end


value = mw.text.trim(tostring(value)):lower()
v = mw.text.trim(tostring(v)):lower()


return value == 'true'
return v ~= ''
or value == 'yes'
and v ~= '0'
or value == '1'
and v ~= 'false'
or value == 'resolved'
and v ~= 'no'
end
and v ~= 'off'
 
 
local function trim(value)
if value == nil then
return ''
end
 
return mw.text.trim(tostring(value))
end
end




local function formatUser(user)
local function formatUser(user)
user = trim(user)
user = mw.text.trim(tostring(user or ''))


if user == '' then
if user == '' or user:lower() == 'anonymous' then
return 'Anonymous'
return 'Anonymous'
end
end
Line 43: Line 35:




local function currentSubjectPage()
local function escapeAttribute(value)
local title = mw.title.getCurrentTitle()
value = tostring(value or '')
 
if title.subjectPageTitle then
return title.subjectPageTitle.fullText
end
 
return title.fullText
end
 
 
local function getBucket()
if not (mw.ext and mw.ext.bucket) then
return nil
end
 
return mw.ext.bucket('feedback')
end
 
 
local function sortNewestFirst(entries)
table.sort(
entries,
function(a, b)
local aDate = trim(a.createddate)
local bDate = trim(b.createddate)


return aDate > bDate
return mw.text.nowiki(value)
end
)
 
return entries
end
 
 
local function queryFeedback(page)
local bucket = getBucket()
 
if not bucket then
return {}
end
 
local query = bucket
 
query.select(
'page',
'user',
'status',
'feedback',
'id',
'createddate',
'link',
'image',
'resolvedby',
'resolveddate'
)
 
query.where(
'page',
page
)
 
local success, results = pcall(function()
return query.run()
end)
 
if not success or not results then
return {}
end
 
return sortNewestFirst(results)
end
end




------------------------------------------------------------
------------------------------------------------------------
-- ATTACHMENTS
-- Feedback card
------------------------------------------------------------
------------------------------------------------------------


local function renderAttachments(entry)
local function renderCard(entry, showInstruction)
local wrapper =
mw.html.create('div')
:addClass('feedback-attachments')


local link = trim(entry.link)
local resolved = (entry.status == 'resolved')


if link ~= '' then
local user = entry.user or 'Anonymous'
local linkWrapper =
local feedback = entry.feedback or 'No feedback provided'
wrapper:tag('span')
local page = entry.page
:addClass('feedback-attachment-link')
local id = entry.id
local resolvedBy = entry.resolvedby
linkWrapper:tag('span')
local resolvedDate = entry.resolveddate
:addClass('feedback-attachment-icon')
linkWrapper:wikitext(
'[' .. link .. ' ' .. mw.text.nowiki(link) .. ']'
)
end


local image = trim(entry.image)


if image ~= '' then
local root = mw.html.create('div')
image = mw.ustring.gsub(
:addClass('feedback-box')
image,
:addClass(
'^File:',
resolved
''
and 'feedback-box--resolved'
or 'feedback-box--unresolved'
)
)


local title =
mw.title.new('File:' .. image)


if title then
--------------------------------------------------------
local imageWrapper =
-- Metadata
wrapper:tag('span')
--------------------------------------------------------
:addClass('feedback-attachment-image')
imageWrapper:tag('span')
:addClass('feedback-attachment-icon')
imageWrapper:wikitext(
'[' ..
title:fullUrl() ..
' ' ..
mw.text.nowiki(image) ..
']'
)
end
end


return wrapper
local meta = root:tag('div')
end
:addClass('feedback-meta')




------------------------------------------------------------
if page and page ~= '' then
-- RESOLUTION
------------------------------------------------------------


local function renderResolution(parent, entry)
meta:tag('span')
local resolvedBy = trim(entry.resolvedby)
:addClass('feedback-page')
local resolvedDate = trim(entry.resolveddate)
:wikitext(
 
string.format('[[%s]]', page)
if resolvedBy == '' and resolvedDate == '' then
return
end
 
local resolution =
parent:tag('div')
:addClass('feedback-resolution')
 
resolution:wikitext('Resolved by ')
 
if resolvedBy ~= '' then
resolution:wikitext(
formatUser(resolvedBy)
)
else
resolution:wikitext('Unknown')
end
 
if resolvedDate ~= '' then
resolution:wikitext(
' on ' .. mw.text.nowiki(resolvedDate)
)
end
end
 
 
------------------------------------------------------------
-- RESOLVE CONTROL
------------------------------------------------------------
 
local function renderResolveControl(
parent,
id,
page,
compact
)
if trim(id) == '' then
return
end
 
local wrapper =
parent:tag('div')
:addClass('feedback-resolve')
 
local control =
wrapper:tag('span')
:addClass('feedback-resolve-button')
:attr(
'data-feedback-id',
id
)
:attr(
'data-feedback-page',
page or ''
)
:attr(
'role',
'button'
)
:attr(
'tabindex',
'0'
)
:attr(
'aria-label',
'Resolve feedback'
)
)


if compact then
meta:tag('span')
control
:addClass('feedback-separator')
:addClass(
:wikitext(' • ')
'feedback-resolve-button--compact'
)
:attr(
'title',
'Resolve feedback'
)
:wikitext('✓')
else
control:wikitext('Resolve')
end
end
 
 
------------------------------------------------------------
-- FULL FEEDBACK CARD
------------------------------------------------------------
 
local function renderFullCard(entry)
local resolved =
trim(entry.status):lower() == 'resolved'


local id = trim(entry.id)
local page = trim(entry.page)
local feedback = trim(entry.feedback)
local user = trim(entry.user)
local createddate = trim(entry.createddate)
local root =
mw.html.create('div')
:addClass('feedback-box')
:addClass(
resolved
and 'feedback-box--resolved'
or 'feedback-box--unresolved'
)
if id ~= '' then
root:attr(
'data-feedback-id',
id
)
end
end


--------------------------------------------------------
-- Main content column
--------------------------------------------------------


local content =
meta:tag('span')
root:tag('div')
:addClass('feedback-user')
:addClass('feedback-content')
:wikitext(formatUser(user))


--------------------------------------------------------
-- Main line
--------------------------------------------------------


local main =
meta:tag('span')
content:tag('div')
:addClass('feedback-separator')
:addClass('feedback-main-line')
:wikitext(' • ')


--------------------------------------------------------
-- Status
--------------------------------------------------------


main:tag('span')
meta:tag('span')
:addClass('feedback-status')
:addClass('feedback-status')
:addClass(
:addClass(
Line 329: Line 112:
or 'Unresolved'
or 'Unresolved'
)
)


--------------------------------------------------------
--------------------------------------------------------
Line 334: Line 118:
--------------------------------------------------------
--------------------------------------------------------


main:tag('span')
root:tag('div')
:addClass('feedback-text')
:addClass('feedback-body')
:wikitext(
:wikitext(feedback)
feedback ~= ''
 
and feedback
or 'No feedback provided'
)


--------------------------------------------------------
--------------------------------------------------------
-- Metadata
-- Resolution information
--------------------------------------------------------
--------------------------------------------------------


local meta =
if resolved and resolvedBy and resolvedBy ~= '' then
main:tag('span')
 
:addClass('feedback-inline-meta')
local resolutionMeta =
'Resolved by ' .. formatUser(resolvedBy)
 
if resolvedDate and resolvedDate ~= '' then
resolutionMeta =
resolutionMeta
.. ' on '
.. resolvedDate
end
 
root:tag('div')
:addClass('feedback-resolution')
:wikitext(resolutionMeta)


if user ~= '' then
meta:wikitext(
' · ' .. formatUser(user)
)
end
end


if createddate ~= '' then
meta:wikitext(
' · ' .. mw.text.nowiki(createddate)
)
end


--------------------------------------------------------
--------------------------------------------------------
-- Attachments
-- Resolution controls
--------------------------------------------------------
--------------------------------------------------------
content:node(
    renderAttachments(entry)
)


--------------------------------------------------------
if showInstruction and not resolved then
-- Resolution information
--------------------------------------------------------


renderResolution(
local instruction = root:tag('div')
content,
:addClass('feedback-instruction')
entry
)


--------------------------------------------------------
-- Missing ID warning
--------------------------------------------------------


if id == '' then
instruction:tag('span')
content:tag('div')
:addClass('feedback-missing-id')
:wikitext(
:wikitext(
'This feedback entry is missing an ID.'
'If this feedback has been resolved, '
.. 'click the button below.'
)
)
end


--------------------------------------------------------
-- Resolve button
--
-- IMPORTANT:
-- This is outside .feedback-content so it
-- remains on the right.
--------------------------------------------------------


if not resolved then
if id and id ~= '' then
renderResolveControl(
 
root,
instruction:tag('button')
id,
:addClass('feedback-resolve-button')
page,
:attr('type', 'button')
false
:attr('data-feedback-id', escapeAttribute(id))
)
:wikitext('Resolve')
 
end
 
end
end


return tostring(root)
return tostring(root)
Line 413: Line 181:


------------------------------------------------------------
------------------------------------------------------------
-- COMPACT CARD
-- Save feedback
------------------------------------------------------------
------------------------------------------------------------


local function renderCompactCard(entry)
local function saveFeedback(data)
return renderFullCard(entry)
end


if not (mw.ext and mw.ext.bucket) then
return false, 'Bucket extension is not available'
end


------------------------------------------------------------
-- SAVE FEEDBACK
------------------------------------------------------------


local function saveFeedback(data)
local bucket = mw.ext.bucket('feedback')
local bucket = getBucket()


if not bucket then
if not bucket then
return false, 'Bucket extension is not available'
return false, 'Feedback bucket could not be opened'
end
end


local success, err = pcall(function()
local success, err = pcall(function()
bucket.put({
bucket.put({
page = data.page,
page = data.page,
user = data.user,
user = data.user,
status = data.status,
status = data.status,
feedback = data.feedback,
feedback = data.feedback
id = data.id,
createddate = data.createddate,
link = data.link,
image = data.image,
resolvedby = data.resolvedby,
resolveddate = data.resolveddate
})
})
end)
end)


if not success then
if not success then
return false, tostring(err)
return false, tostring(err)
end
end


return true
return true
Line 456: Line 220:


------------------------------------------------------------
------------------------------------------------------------
-- MAIN
-- Main
--
--
-- Used by Template:Feedback
-- Used by Template:Feedback
--
-- Example:
--
-- {{Feedback
--  |feedback=Something could be improved here.
--  |user=Rei
--  |resolved=false
--  |id=1758012345678
--  |resolvedby=
--  |resolveddate=
-- }}
------------------------------------------------------------
------------------------------------------------------------


function p.main(frame)
function p.main(frame)
local parent = frame:getParent()
local parent = frame:getParent()


Line 467: Line 243:
parent and parent.args
parent and parent.args
or frame.args
or frame.args
--------------------------------------------------------
-- Get page title
--------------------------------------------------------


local pageTitle = nil
local pageTitle = nil


if parent and parent.getTitle then
if parent and parent.getTitle then
local title = parent:getTitle()
local title = parent:getTitle()


Line 479: Line 261:
pageTitle = title
pageTitle = title
end
end
end
end


return p._main(
 
args,
return p._main(args, pageTitle)
pageTitle
 
)
end
end




function p._main(args, pageTitle)
function p._main(args, pageTitle)
local feedback =
local feedback =
trim(args.feedback)
args.feedback
or 'No feedback provided'


if feedback == '' then
feedback = 'No feedback provided'
end


local user =
local user =
trim(args.user)
args.user
or 'Anonymous'


if user == '' then
user = 'Anonymous'
end


local resolved =
local resolved =
isTruthy(args.resolved)
isTruthy(args.resolved)


local status =
local status =
Line 511: Line 291:
or 'unresolved'
or 'unresolved'


local currentPage =
trim(pageTitle)


if currentPage == '' then
local id =
currentPage =
mw.text.trim(
mw.title.getCurrentTitle().fullText
tostring(args.id or '')
end
)
 


local id =
local resolvedBy =
trim(args.id)
mw.text.trim(
tostring(args.resolvedby or '')
)


local createddate =
trim(args.createddate)


local link =
local resolvedDate =
trim(args.link)
mw.text.trim(
tostring(args.resolveddate or '')
)


local image =
trim(args.image)


local resolvedby =
local currentPage =
trim(args.resolvedby)
pageTitle
or mw.title.getCurrentTitle().fullText


local resolveddate =
trim(args.resolveddate)


--------------------------------------------------------
--------------------------------------------------------
Line 541: Line 319:
--------------------------------------------------------
--------------------------------------------------------


local saved, saveError =
local saved, saveError = saveFeedback({
saveFeedback({
page = currentPage,
page = currentPage,
user = user,
user = user,
status = status,
status = status,
feedback = feedback
feedback = feedback,
})
id = id,
 
createddate = createddate,
link = link,
image = image,
resolvedby = resolvedby,
resolveddate = resolveddate
})


if not saved then
if not saved then
return
 
'<strong style="color:red;">Feedback bucket error: '
return '<strong style="color:red;">Feedback bucket error: '
.. mw.text.nowiki(
.. mw.text.nowiki(saveError or 'Unknown error')
saveError or 'Unknown error'
)
.. '</strong>'
.. '</strong>'
end
end


--------------------------------------------------------
--------------------------------------------------------
-- Render
-- Render feedback card
--------------------------------------------------------
--------------------------------------------------------


local card =
local card = renderCard({
renderFullCard({
 
page = currentPage,
page = nil,
user = user,
 
status = status,
user = user,
feedback = feedback,
 
id = id,
status = status,
createddate = createddate,
 
link = link,
feedback = feedback,
image = image,
 
resolvedby = resolvedby,
id = id,
resolveddate = resolveddate
 
})
resolvedby = resolvedBy,
 
resolveddate = resolvedDate
 
}, true)
 


--------------------------------------------------------
--------------------------------------------------------
-- Categories
-- Categorize feedback
--------------------------------------------------------
--------------------------------------------------------


Line 589: Line 366:


if resolved then
if resolved then
category =
category =
'[[Category:Resolved Feedback]]'
'[[Category:Resolved Feedback]]'
else
else
category =
category =
'[[Category:Unresolved Feedback]]'
'[[Category:Unresolved Feedback]]'
end
end


if id == '' then
category =
category ..
'[[Category:Feedbacks Missing ID]]'
end


return card .. category
return card .. category
end
end




------------------------------------------------------------
------------------------------------------------------------
-- RENDER FEEDBACK LIST
-- Render feedback list
------------------------------------------------------------
------------------------------------------------------------


local function renderFeedbackList(results)
local function renderFeedbackList(results)
if not results or #results == 0 then
if not results or #results == 0 then
return '<em>No feedback entries found.</em>'
return '<em>No feedback entries found.</em>'
end
end


local list = {}
local list = {}


for _, row in ipairs(results) do
for _, row in ipairs(results) do
table.insert(
table.insert(
list,
list,
renderFullCard(row)
renderCard(row, false)
)
)
end
end


return table.concat(
 
list,
return table.concat(list, '\n')
'\n'
 
)
end
end




------------------------------------------------------------
------------------------------------------------------------
-- PAGE FEEDBACK
-- View feedback
------------------------------------------------------------
------------------------------------------------------------


function p.page(frame)
function p.view(frame)
local page =
currentSubjectPage()


local entries =
local parent = frame:getParent()
queryFeedback(page)


local unresolved = {}
local resolved = {}


for _, entry in ipairs(entries) do
local args
if trim(entry.status):lower()
 
== 'resolved'
if frame
then
and frame.args
table.insert(
and frame.args.status
resolved,
then
entry
 
)
args = frame.args
else
 
table.insert(
elseif parent
unresolved,
and parent.args
entry
and parent.args.status
)
then
end
 
args = parent.args
 
elseif frame
and frame.args
then
 
args = frame.args
 
elseif parent
and parent.args
then
 
args = parent.args
 
else
 
args = {}
 
end
end


local root =
mw.html.create('section')
:attr(
'id',
'feedback-section'
)
:addClass('feedback-page')


--------------------------------------------------------
return p._view(args, frame)
-- Heading
 
--------------------------------------------------------
end
 


root:tag('h2')
function p._view(args, frame)
:addClass('feedback-page-title')
:wikitext('Feedbacks')


--------------------------------------------------------
--------------------------------------------------------
-- Filters
-- Check Bucket
--------------------------------------------------------
--------------------------------------------------------


local filters =
if not (mw.ext and mw.ext.bucket) then
root:tag('div')
 
:addClass('feedback-filters')
return
'<em>Bucket extension is not available.</em>'


local function addFilter(
label,
value,
active
)
return filters:tag('button')
:attr(
'type',
'button'
)
:attr(
'data-feedback-filter',
value
)
:addClass('feedback-filter')
:addClass(
active
and 'feedback-filter--active'
or nil
)
:wikitext(label)
end
end


addFilter(
'Unresolved',
'unresolved',
true
)


addFilter(
frame = frame or mw.getCurrentFrame()
'Resolved',
'resolved',
false
)


addFilter(
'All',
'all',
false
)


--------------------------------------------------------
--------------------------------------------------------
-- Unresolved
-- Determine requested status
--------------------------------------------------------
--------------------------------------------------------


local unresolvedList =
local rawStatus =
root:tag('div')
args.status
:addClass(
or args[1]
'feedback-page-list'
 
)
 
:addClass(
local filterStatus =
'feedback-page-list--unresolved'
rawStatus
)
and mw.text.trim(rawStatus):lower()
:addClass(
or nil
'feedback-page-list--visible'
)


if #unresolved == 0 then
unresolvedList:tag('div')
:addClass('feedback-empty')
:wikitext(
'No unresolved feedback.'
)
else
for _, entry in ipairs(unresolved) do
unresolvedList:wikitext(
renderCompactCard(entry)
)
end
end


--------------------------------------------------------
--------------------------------------------------------
-- Resolved
-- Specific status
--------------------------------------------------------
--------------------------------------------------------


local resolvedList =
if filterStatus == 'resolved'
root:tag('div')
or filterStatus == 'unresolved'
:addClass(
then
'feedback-page-list'
 
)
local query =
:addClass(
mw.ext.bucket('feedback')
'feedback-page-list--resolved'
 
)
 
query.select(
'page',
'user',
'status',
'feedback'
)
 
 
query.where(
'status',
filterStatus
)
 
 
return renderFeedbackList(
query.run()
)


if #resolved == 0 then
resolvedList:tag('div')
:addClass('feedback-empty')
:wikitext(
'No resolved feedback.'
)
else
for _, entry in ipairs(resolved) do
resolvedList:wikitext(
renderCompactCard(entry)
)
end
end
end


--------------------------------------------------------
--------------------------------------------------------
-- All
-- All feedback
--------------------------------------------------------
--------------------------------------------------------


local allList =
if filterStatus == 'all' then
root:tag('div')
:addClass(
'feedback-page-list'
)
:addClass(
'feedback-page-list--all'
)


if #entries == 0 then
local query =
allList:tag('div')
mw.ext.bucket('feedback')
:addClass('feedback-empty')
:wikitext(
'No feedback.'
)
else
for _, entry in ipairs(entries) do
allList:wikitext(
renderCompactCard(entry)
)
end
end


return tostring(root)
end


query.select(
'page',
'user',
'status',
'feedback'
)


------------------------------------------------------------
-- COUNTS
------------------------------------------------------------


function p.counts(frame)
return renderFeedbackList(
local entries =
query.run()
queryFeedback(
currentSubjectPage()
)
)


local unresolved = 0
end
local resolved = 0


for _, entry in ipairs(entries) do
if trim(entry.status):lower()
== 'resolved'
then
resolved = resolved + 1
else
unresolved = unresolved + 1
end
end


return tostring(
--------------------------------------------------------
mw.html.create('span')
-- Tabber mode
:addClass('feedback-count-data')
--------------------------------------------------------
:attr(
'data-unresolved',
unresolved
)
:attr(
'data-resolved',
resolved
)
)
end


local qAll =
mw.ext.bucket('feedback')


------------------------------------------------------------
-- TABLE / DASHBOARD
------------------------------------------------------------


local function renderTable(entries)
qAll.select(
if not entries or #entries == 0 then
'page',
return '<em>No feedback entries found.</em>'
'user',
end
'status',
'feedback'
)


local table =
mw.html.create('table')
:addClass('feedback-table')


local head =
local allEntries =
table:tag('thead')
qAll.run()
:tag('tr')


head:tag('th')
:wikitext('Status')


head:tag('th')
local allList = {}
:wikitext('Page')
local unresolvedList = {}
local resolvedList = {}


head:tag('th')
:wikitext('Feedback')


head:tag('th')
--------------------------------------------------------
:wikitext('User')
-- Split entries by status
--------------------------------------------------------


head:tag('th')
if allEntries and #allEntries > 0 then
:wikitext('Date')


local body =
for _, row in ipairs(allEntries) do
table:tag('tbody')


for _, entry in ipairs(entries) do
local card =
local row =
renderCard(row, false)
body:tag('tr')


local resolved =
trim(entry.status):lower()
== 'resolved'


row:tag('td')
table.insert(
:addClass(
allList,
resolved
card
and 'feedback-table-status--resolved'
or 'feedback-table-status--unresolved'
)
:wikitext(
resolved
and 'Resolved'
or 'Unresolved'
)
)


row:tag('td')
:addClass('feedback-table-page')
:wikitext(
entry.page or ''
)


row:tag('td')
if row.status == 'resolved' then
:addClass('feedback-table-text')
 
:wikitext(
table.insert(
entry.feedback or ''
resolvedList,
)
card
)


row:tag('td')
else
:wikitext(
formatUser(entry.user)
)


row:tag('td')
table.insert(
:wikitext(
unresolvedList,
entry.createddate or ''
card
)
)
end


return tostring(table)
end
end


end


function p.view(frame)
end
local parent =
frame:getParent()


local args


if frame
--------------------------------------------------------
and frame.args
-- Build tab contents
and frame.args.status
--------------------------------------------------------
then
args = frame.args


elseif parent
local allContent
and parent.args
and parent.args.status
then
args = parent.args


elseif frame
if #allList > 0 then
and frame.args
then
args = frame.args


elseif parent
allContent =
and parent.args
table.concat(allList, '\n')
then
args = parent.args


else
else
args = {}
 
allContent =
'<em>No feedback entries found.</em>'
 
end
end


return p._view(
args,
frame
)
end


local unresolvedContent
if #unresolvedList > 0 then
unresolvedContent =
table.concat(unresolvedList, '\n')
else


function p._view(args, frame)
unresolvedContent =
local bucket =
'<em>No unresolved feedback entries found.</em>'
getBucket()


if not bucket then
return
'<em>Bucket extension is not available.</em>'
end
end


local rawStatus =
args.status
or args[1]


local filterStatus =
local resolvedContent
rawStatus
and trim(rawStatus):lower()
or nil


--------------------------------------------------------
if #resolvedList > 0 then
-- Query
--------------------------------------------------------


local query =
resolvedContent =
bucket
table.concat(resolvedList, '\n')


query.select(
else
'page',
'user',
'status',
'feedback',
'id',
'createddate',
'link',
'image',
'resolvedby',
'resolveddate'
)
 
if filterStatus == 'resolved'
or filterStatus == 'unresolved'
then
query.where(
'status',
filterStatus
)
end


local success, entries =
resolvedContent =
pcall(function()
'<em>No resolved feedback entries found.</em>'
return query.run()
end)


if not success or not entries then
return
'<em>Could not load feedback.</em>'
end
end


entries =
sortNewestFirst(entries)


--------------------------------------------------------
--------------------------------------------------------
-- Specific status
-- Tabber
--------------------------------------------------------
--------------------------------------------------------


if filterStatus == 'resolved'
local tabberBody = string.format(
or filterStatus == 'unresolved'
'All=\n%s\n|-|Unresolved=\n%s\n|-|Resolved=\n%s',
then
allContent,
return renderFeedbackList(
unresolvedContent,
entries
resolvedContent
)
)
end
 


--------------------------------------------------------
return frame:callParserFunction(
-- All
'#tag',
--------------------------------------------------------
{
'tabber',
tabberBody
}
)


return renderTable(entries)
end
end


p.table = p.view


return p
return p
Please note that all contributions to The Petit Planet Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Petit Planet Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)
Preview page with this template
Below are commonly used wikitext from MediaWiki:Edittools. Click on any to insert them in the edit box.
File Pages==Summary====Licensing=={{Fairuse}}{{File|}}
Dynamic Page List¦²«»²{¦}²«»«/»«!----»
Array in DPL¹^2{}^2^2{¹}^2
Parser Functions{{#if:||}}
{{#ifeq:|||}}
{{#expr:}}
{{#switch:||#default=}}
{{#replace:||}}
{{#titleparts:}}
{{#tag:|}}
Markup{{}}|[][[]][[Category:]]#REDIRECT [[]] [[Category:Redirect Pages]]<code></code><includeonly></includeonly><noinclude></noinclude><nowiki></nowiki><!----><br>§
Notices{{Stub|}}{{Stub Dialogue}}{{Upcoming}}{{Under Construction}}{{Placeholder|}}
Magic Words{{!}}{{formatnum:}}{{lc:}}{{uc:}}{{PAGENAME}}{{FULLPAGENAME}}{{ROOTPAGENAME}}{{BASEPAGENAME}}{{SUBPAGENAME}}{{DISPLAYTITLE:|noreplace}}__TOC____NOTOC____EXPECTUNUSEDCATEGORY____HIDDENCAT__
HTML Entities&mdash;&nbsp;&comma;&shy;