Module:ScriptItem: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
(108 intermediate revisions by 3 users not shown) | |||
Line 37: | Line 37: | ||
p.categoryWords = { | p.categoryWords = { | ||
-- Category Names. (String(s) to look for in an item name, case-INsensitive.) | -- Category Names. (String(s) to look for in an item name, case-INsensitive.) | ||
'Blip', 'Building', 'Camera', 'Chatbox | 'Blip', 'Building', 'Camera', 'Chatbox', 'Cheat', 'Client', 'Command', 'Cursor', 'Debug', 'Dodo', | ||
'Element', 'Entity', 'Event', 'File', 'Garage', 'HTTP', 'HUD', 'Key', 'Mission', 'Mouse', 'Network', 'Object', | 'Element', 'Entity', 'Event', 'File', 'Font', 'Garage', 'HTTP', 'HUD', 'Key', 'Mission', 'Mouse', 'NetFlags', 'Network', 'Object', | ||
'Pause', 'Ped', 'Pickup', 'Player', 'Process', 'Render', 'Resource', 'Screen', 'Socket', 'Sphere', 'Time | 'Pause', 'Ped', 'Pickup', 'Player', 'Process', 'Render', 'Resource', 'Screen', 'Socket', 'Sphere', 'Time', 'Vehicle', 'Weather', 'World' | ||
} | } | ||
Line 63: | Line 63: | ||
-- item page types | -- item page types | ||
function p.showVariablePage(frame) | function p.showVariablePage(frame) | ||
return p.showPage(frame, { "Value" }) | |||
return p.showPage(frame, | |||
end | end | ||
function p.showFunctionPage(frame) | function p.showFunctionPage(frame) | ||
return p.showPage(frame, { "Parameters", "Return", "Callbacks" }) | |||
end | end | ||
function p.showPropertyPage(frame) | function p.showPropertyPage(frame) | ||
return p.showPage(frame, { "Value" }) | |||
return p.showPage(frame, | |||
end | end | ||
function p.showMethodPage(frame) | function p.showMethodPage(frame) | ||
return p.showPage(frame, { "Parameters", "Return", "Callbacks" }) | |||
end | end | ||
function p.showEventPage(frame) | function p.showEventPage(frame) | ||
return p.showPage(frame, { "Parameters", "Attributes" }) | |||
end | end | ||
Line 90: | Line 85: | ||
function p.showPage(frame, parts) | function p.showPage(frame, parts) | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
if args.type ~= 'event' then | |||
table.insert(parts, "Types") | |||
end | |||
--table.insert(parts, "Symbols") | |||
local lines = p.getPageTopLines(frame) | local lines = p.getPageTopLines(frame) | ||
for i,part in ipairs({"Notes", "Examples", "Compatibility", "Related"}) do | for i,part in ipairs({"Notes", "Examples", "Compatibility", "Related"}) do | ||
Line 95: | Line 94: | ||
end | end | ||
for i,part in ipairs(parts) do | for i,part in ipairs(parts) do | ||
local data = p[part:lower()](frame) | local data = p[part:lower() == 'return' and 'returns' or part:lower()](frame) | ||
if data and #data > 0 then | if data and #data > 0 then | ||
if part == 'Settable' then | if part == 'Settable' then | ||
Line 110: | Line 109: | ||
local lines = {} | local lines = {} | ||
table.insert(lines, frame:preprocess("{{DISPLAYTITLE:"..p.getDisplayedName(frame).."}}")) | table.insert(lines, frame:preprocess("{{DISPLAYTITLE:"..p.getDisplayedName(frame).."}}")) | ||
table.insert(lines, "__NOTOC__"..p.getPageTopBoxes(frame).."< | |||
table.insert(lines, p. | -- Added for discord embed styling | ||
table.insert(lines, p. | --table.insert(lines, "<meta content='"..p.getDisplayedName(frame).."' property='og:title' />")) | ||
--table.insert(lines, "<meta content='"..p.description(frame).."' property='og:description' />")) | |||
--table.insert(lines, "<meta content='#04C765' data-react-helmet='true' name='theme-color' />")) | |||
table.insert(lines, "__NOTOC__"..p.getPageTopBoxes(frame).."\n") | |||
table.insert(lines, "<div style='margin-top: 20px;'>Available since "..p.since(frame).."</div>\n") | |||
table.insert(lines, "<div style='margin-top: 6px;'>\n"..p.syntax(frame).."</div>\n") | |||
table.insert(lines, "<div style='margin-top: 20px;'>\n"..p.description(frame).."</div>\n") | |||
return lines | return lines | ||
end | end | ||
Line 122: | Line 128: | ||
if args.type == 'variable' or args.type == 'property' then | if args.type == 'variable' or args.type == 'property' then | ||
table.insert(topBoxes, "settable") | table.insert(topBoxes, "settable") | ||
elseif args.type == 'event' then | |||
table.insert(topBoxes, "cancellable") | |||
end | end | ||
Line 128: | Line 136: | ||
table.insert(outBoxes, p[topBox.."Box"](frame)) | table.insert(outBoxes, p[topBox.."Box"](frame)) | ||
end | end | ||
return table.concat(outBoxes, ' ') | return table.concat(outBoxes, ' ').."<br>" | ||
end | end | ||
Line 274: | Line 282: | ||
local gamesText = p.getGames(args.games) | local gamesText = p.getGames(args.games) | ||
if gamesText == "All Games" then | if gamesText == "All Games" then | ||
return p.loadTemplate(frame, 'GreenInformationBox', { | return p.loadTemplate(frame, 'GreenInformationBox', {table.concat({ | ||
p.loadTemplate(frame, 'icon-iii'), | |||
p.loadTemplate(frame, 'icon-vc'), | |||
p.loadTemplate(frame, 'icon-sa'), | |||
p.loadTemplate(frame, 'icon-iv') | |||
}, ' '), id='games'}) | |||
else | else | ||
return p.loadTemplate(frame, 'RedInformationBox', { | local games = { 'iii', 'vc', 'sa', 'iv' } | ||
local out = {} | |||
for i,game in ipairs(games) do | |||
if gamesText:lower():find(game) then | |||
table.insert(out, p.loadTemplate(frame, 'icon-'..game, {})) | |||
end | |||
end | |||
return p.loadTemplate(frame, 'RedInformationBox', {table.concat(out, ' '), id='games'}) | |||
end | end | ||
end | end | ||
Line 282: | Line 302: | ||
function p.onlineBox(frame) | function p.onlineBox(frame) | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
if args.sp == 'true' then | if args.sp == 'true' or args.online == 'false' then | ||
return p.loadTemplate(frame, 'RedInformationBox', {'Offline Only',id='online'}); | return p.loadTemplate(frame, 'RedInformationBox', {'Offline Only',id='online'}); | ||
elseif args.sp == 'false' or args.offline == 'false' then | |||
return p.loadTemplate(frame, 'RedInformationBox', {'Online Only',id='online'}); | |||
else | else | ||
return p.loadTemplate(frame, 'GreenInformationBox', {'Online and Offline',id='online'}); | return p.loadTemplate(frame, 'GreenInformationBox', {'Online and Offline',id='online'}); | ||
Line 295: | Line 317: | ||
else | else | ||
return p.loadTemplate(frame, 'GreenInformationBox', {'Read and Set',id='settable'}); | return p.loadTemplate(frame, 'GreenInformationBox', {'Read and Set',id='settable'}); | ||
end | |||
end | |||
function p.cancellableBox(frame) | |||
local args = p.getArgs(frame) | |||
if p.isCancellable(frame)then | |||
return p.loadTemplate(frame, 'GreenInformationBox', {'Cancellable',id='cancellable'}); | |||
else | |||
return p.loadTemplate(frame, 'RedInformationBox', {'Not Cancellable',id='cancellable'}); | |||
end | end | ||
end | end | ||
Line 306: | Line 337: | ||
local endpointVersions = p.getEndpointVersions(args.since, args.endpoint) | local endpointVersions = p.getEndpointVersions(args.since, args.endpoint) | ||
if #endpointVersions == 2 then | if #endpointVersions == 2 then | ||
return "'''Server "..endpointVersions[1]..", Client "..endpointVersions[2].."'''" | return "'''Server "..endpointVersions[1].."''', '''Client "..endpointVersions[2].."'''" | ||
else | else | ||
if args.endpoint == 'server' then | if args.endpoint == 'server' then | ||
Line 340: | Line 371: | ||
local entries = p.getIndexedArgs(frame, 'description') | local entries = p.getIndexedArgs(frame, 'description') | ||
local startTextFirstLine = "The '' | local startTextFirstLine = "The <span style=\"font-family: 'Source Code Pro', monospace;\">"..p.getDisplayedNameColoured(frame).."</span> [[HowTo/Functions|"..args.type.."]] is "..(args.type == "event" and "invoked when" or "used to").." " | ||
for i,entry in ipairs(entries) do | for i,entry in ipairs(entries) do | ||
Line 363: | Line 394: | ||
elseif entries[1] == "void" then | elseif entries[1] == "void" then | ||
local headers = nil | local headers = nil | ||
local rows = { { "void", "This "..args.type.." doesn't take any parameters." } } | local rows = { { p.formatType("void", frame), "This "..args.type.." doesn't take any parameters." } } | ||
local widths = { | local widths = { 120, 400 } | ||
return p.table(headers, rows, widths, 'wikitable- | return p.table(headers, rows, widths, 'wikitable-returns wikitable') | ||
else | else | ||
for i,arg in ipairs(entries) do | for i,arg in ipairs(entries) do | ||
Line 371: | Line 402: | ||
local isOptional = tokens[3] == 'optional' | local isOptional = tokens[3] == 'optional' | ||
local defaultValue = isOptional and tokens[4] or "n/a" | local defaultValue = isOptional and "<span style='font-family: \"Source Code Pro\", monospace;'>"..tokens[4].."</span>" or "n/a" | ||
local description = p.formatDescription(table.concat(tokens, ' ', isOptional and 5 or 3)) | local description = p.formatDescription(table.concat(tokens, ' ', isOptional and 5 or 3)) | ||
if isEvent then | if isEvent then | ||
rows[i] = { i..") ", p.formatType(tokens[1], frame), p. | rows[i] = { (i + 1)..") ", p.formatType(tokens[1], frame), p.formatName(tokens[2], frame), description } | ||
else | else | ||
rows[i] = { i..") ", p.formatType(tokens[1], frame), p. | rows[i] = { i..") ", p.formatType(tokens[1], frame), p.formatName(tokens[2], frame), (isOptional and ("Optional, defaults to "..defaultValue..". ") or "")..description } | ||
end | end | ||
end | end | ||
Line 383: | Line 414: | ||
if isEvent then | if isEvent then | ||
table.insert(rows, 1, { "1) ", p.formatType("Event", frame), "event", "The event object for this event." }) | table.insert(rows, 1, { "1) ", p.formatType("Event", frame), p.formatName("event", frame), "The event object for this event." }) | ||
end | end | ||
Line 404: | Line 435: | ||
local headers | local headers | ||
local widths | local widths | ||
local isVoidReturn = false | |||
rows = {} | rows = {} | ||
entries = p.getIndexedArgs(frame, 'return') | entries = p.getIndexedArgs(frame, 'return') | ||
if #entries == 0 then | if #entries == 0 then | ||
text = text..p.documentationMissing(frame, " | text = text..p.documentationMissing(frame, "Returns").."<br><br>" | ||
else | else | ||
for i,arg in ipairs(entries) do | for i,arg in ipairs(entries) do | ||
Line 419: | Line 450: | ||
local description | local description | ||
if type:lower() == "void" then | if type:lower() == "void" then | ||
description = "This "..args.type.." doesn't return | isVoidReturn = true | ||
description = "This "..args.type.." doesn't return a value." | |||
elseif tokens[2] then | elseif tokens[2] then | ||
description = p.formatDescription(table.concat(tokens, ' ', 2)) | description = p.formatDescription(table.concat(tokens, ' ', 2)) | ||
else | else | ||
description = p.documentationMissing(frame, "Description for | description = p.documentationMissing(frame, "Description for return value") | ||
end | end | ||
Line 429: | Line 461: | ||
end | end | ||
headers = nil-- { "Type", "Description" } | headers = nil-- { "Type", "Description" } | ||
widths = { | widths = { 120, 400 } | ||
text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable') | text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable') | ||
end | end | ||
rows = {} | --[[ | ||
-- commented out as failure returns are not currently implemented in GTAC. | |||
if not isVoidReturn then | |||
rows = {} | |||
entries = p.getIndexedArgs(frame, 'returnFail') | |||
text = text.."'''Failure Return:'''\n\n" | |||
if #entries == 0 then | |||
text = text..p.documentationMissing(frame, "Failure returns") | |||
else | |||
for i,arg in ipairs(entries) do | |||
local tokens = p.split(arg, ' ') | |||
local type = tokens[1] | |||
type = p.standardizeNullType(type) | |||
local value | |||
if type:lower() == 'void' then | |||
value = "n/a" | |||
elseif tokens[2] then | |||
value = p.formatSource(table.concat(tokens, ' ', 2), frame) | |||
else | |||
value = p.formatSource(p.documentationMissing(frame, "Description for failure return value"), frame) | |||
end | |||
rows[i] = { p.formatType(tokens[1], frame), value } | |||
end | end | ||
headers = nil--{ "Type", "Value" } | |||
widths = { 120, 400 } | |||
text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable') | |||
end | end | ||
end | end | ||
]] | |||
return text | return text | ||
Line 509: | Line 546: | ||
local description = p.formatDescription(table.concat(callbackTokens, ' ', 3)) | local description = p.formatDescription(table.concat(callbackTokens, ' ', 3)) | ||
rows[i2] = { p.formatType(parameterType, frame), p. | rows[i2] = { i2..') ', p.formatType(parameterType, frame), p.formatName(parameterName, frame), description } | ||
end | end | ||
local headers, widths | local headers, widths | ||
headers = { "Type", "Name", "Description" } | headers = nil--{ "Type", "Name", "Description" } | ||
widths = { | widths = { 30, 80, 110, 400 } | ||
local table2 = "\n"..p.table(headers, rows, widths, 'wikitable-callback wikitable') | local table2 = "\n"..p.table(headers, rows, widths, 'wikitable-callback wikitable') | ||
table.insert(html, table2) | table.insert(html, table2) | ||
Line 539: | Line 576: | ||
end | end | ||
function p. | function p.attributes(frame) | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
local headers = nil--{ "Type", "Description" } | |||
local rows = {} | |||
if p.isCancellable(frame) then | if p.isCancellable(frame) then | ||
rows[1] = { 'cancellable', 'This '..args.type..' can be cancelled, by using [[event.preventDefault|event.preventDefault]].' } | |||
else | else | ||
rows[1] = { p.formatType('const', frame), 'This '..args.type..' cannot be cancelled.' } | |||
end | end | ||
local widths = { 120, 400 } | |||
return p.table(headers, rows, widths, 'wikitable-returns wikitable') | |||
end | end | ||
Line 560: | Line 600: | ||
local description = p.formatDescription(table.concat(tokens, ' ', 2)) | local description = p.formatDescription(table.concat(tokens, ' ', 2)) | ||
local headers = { "Type", "Description" } | local headers = nil--{ "Type", "Description" } | ||
local rows = { { p.formatType(tokens[1], frame), description } } | local rows = {} | ||
local widths = { | rows[1] = { p.formatType(tokens[1], frame), description } | ||
return p.table(headers, rows, widths, 'wikitable- | if args.readonly == 'true' then | ||
rows[2] = { p.formatType('readonly', frame), 'This '..args.type..' cannot be changed.' } | |||
else | |||
rows[2] = { 'read/set', 'This '..args.type..' can be changed, as well as read.' } | |||
end | |||
local widths = { 120, 400 } | |||
return p.table(headers, rows, widths, 'wikitable-returns wikitable') | |||
end | end | ||
Line 578: | Line 624: | ||
function p.types(frame) | function p.types(frame) | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
return p. | return p.getTypesText(frame, args.class) | ||
end | |||
function p.symbols(frame) | |||
local args = p.getArgs(frame) | |||
return p.getSymbolsText(frame, args.class) | |||
end | end | ||
Line 760: | Line 811: | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
if p.isOOP(frame) then | if p.isOOP(frame) then | ||
return args.class | return p.lowerFirstCharCase(args.class).."."..args.name | ||
else | else | ||
return args.name | return args.name | ||
end | |||
end | |||
function p.getTypeRgb() | |||
return '#009106' | |||
end | |||
function p.getNameRgb() | |||
return '#0645ad' | |||
end | |||
function p.getDisplayedNameColoured(frame) | |||
local typeRgb = p.getTypeRgb() | |||
local nameRgb = p.getNameRgb() | |||
local args = p.getArgs(frame) | |||
if p.isOOP(frame) then | |||
return "<span style='color:"..typeRgb..";'>"..p.lowerFirstCharCase(args.class).."</span>.<span style='color:"..nameRgb.."';>"..args.name.."</span>" | |||
else | |||
return "<span style='color:"..nameRgb.."';>"..args.name.."</span>" | |||
end | end | ||
end | end | ||
Line 805: | Line 875: | ||
end | end | ||
function p. | function p.getTypesText(frame, baseType) | ||
local args = p.getArgs(frame) | local args = p.getArgs(frame) | ||
local derivedTypes = { | local derivedTypes = { | ||
ped = { | ped = {'Player'}, | ||
physical = {'Object', 'Ped', 'Vehicle | physical = {'Object', 'Ped', 'Vehicle', 'Player'}, | ||
entity = {'Building', 'Physical', 'Object', 'Ped', 'Vehicle | entity = {'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Player'}, | ||
element = {'Blip', 'Entity', 'Marker', 'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Player'}, | |||
vehicle = {'Train'}, | |||
event = {'CancellableEvent', 'KeyEvent'}, | |||
surface = {'RenderTarget', 'Texture'} | |||
} | } | ||
local | local serverTypes = {} | ||
local sharedTypes = { | |||
'Building', 'Client', 'Effect', 'Event', 'Timer', 'ReflectedFunction', 'Resource', 'Stream', 'Vec2', 'Vec3', 'Matrix4x4', | |||
'Element', 'Blip', 'Pickup', 'Entity', 'Physical','Vehicle', 'Train', 'XmlDocument', 'XmlElement', | |||
'CancellableEvent', 'KeyEvent', 'Marker', 'Object', 'Ped', 'Player' | |||
} | |||
local out = {} | |||
local getTypeSide = function(type) | |||
for i2,type2 in ipairs(serverTypes) do | |||
if type:lower() == type2:lower() then | |||
return 'server' | |||
end | |||
end | |||
for i2,type2 in ipairs(sharedTypes) do | |||
if type:lower() == type2:lower() then | |||
return 'shared' | |||
end | |||
end | |||
return 'client' | |||
end | |||
if derivedTypes[baseTypeLower] then | if baseType then | ||
local baseTypeLower = baseType:lower() | |||
local allTypes | |||
for i,type in ipairs( | if derivedTypes[baseTypeLower] then | ||
allTypes = p.copyTable(derivedTypes[baseTypeLower]) | |||
table.insert(allTypes, 1, baseType) | |||
else | |||
allTypes = { baseType } | |||
end | |||
local types = {} | |||
for i,type in ipairs(allTypes) do | |||
types[i] = type | types[i] = type | ||
end | end | ||
p.sortTable(types) | p.sortTable(types) | ||
for i,type in ipairs(types) do | |||
types[i] = p.loadTemplate(frame, 'Side', {[getTypeSide(type)]='1'}).." ".."<span style=\"font-family: 'Source Code Pro', monospace;\">"..type.."</span>" | |||
end | |||
--table.insert(out, "<div style='margin-top: 20px;'></div>") | |||
table.insert(out, "\n"..table.concat(types, "<br>")) | |||
end | |||
return table.concat(out, "") | |||
end | |||
function p.getSymbolsText(frame, baseType) | |||
local args = p.getArgs(frame) | |||
local out = {} | |||
local rows = {} | |||
if args.type == 'function' or args.type == 'variable' then | |||
local parts = p.split(p.getDisplayedName(frame), ".") | |||
for i=1,(#parts)-1,1 do | |||
rows[i] = {} | |||
rows[i][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[i].."</span>" | |||
rows[i][2] = 'Namespace' | |||
rows[i][3] = i == 1 and 'Global' or 'Namespace: '..parts[i-1] | |||
rows[i][4] = i == 1 and parts[i]..' is a namespace, which exists in the global namespace.' or parts[i]..' is a namespace, which exists in the '..parts[i-1]..' namespace.' | |||
end | |||
rows[#parts] = {} | |||
rows[#parts][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[#parts].."</span>" | |||
rows[#parts][2] = p.properCase(args.type) | |||
rows[#parts][3] = #parts == 1 and 'Global' or 'Namespace: '..parts[#parts-1] | |||
rows[#parts][4] = #parts == 1 and parts[1]..' is a '..p.properCase(args.type)..', which exists in the global namespace.' or parts[#parts]..' is a '..p.properCase(args.type)..', which exists in the '..parts[#parts-1]..' namespace.' | |||
elseif args.type == 'method' or args.type == 'property' then | |||
local parts = p.split(p.getDisplayedName(frame), ".") | |||
rows[1] = {} | |||
rows[1][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[1].."</span>" | |||
rows[1][2] = 'Object' | |||
rows[1][3] = 'n/a' | |||
rows[1][4] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[1].."</span>"..' is an object.' | |||
rows[2] = {} | |||
rows[2][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[2].."</span>" | |||
rows[2][2] = p.properCase(args.type) | |||
rows[2][3] = #parts == 1 and 'Global' or 'Namespace: '..parts[#parts-1] | |||
rows[2][4] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[2].."</span>"..' is a '..p.properCase(args.type)..', which is used on objects of type '..parts[1] | |||
elseif args.type == 'event' then | |||
rows[1] = {} | |||
rows[1][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..p.getDisplayedName(frame).."</span>" | |||
rows[1][2] = 'String' | |||
rows[1][3] = 'n/a' | |||
rows[1][4] = 'Events are referenced by name. Event names use data type String.' | |||
end | |||
--table.insert(out, "<div style='margin-top: 20px;'></div>") | |||
local headers = { 'Symbol Name', 'Symbol Type', 'Container', 'Description' } | |||
table.insert(out, "\n"..p.table(headers, rows, { 120, 120, 400 }, false)) | |||
if args.type ~= 'event' then | |||
local languages = { 'JS', 'Lua', 'Squirrel' } | |||
local languageSymbols = { | |||
['JS'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'dot', ['property'] = 'dot' }, | |||
['Lua'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'colon', ['property'] = 'dot' }, | |||
['Squirrel'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'dot', ['property'] = 'dot' } | |||
} | |||
for i,language in ipairs(languages) do | |||
local line | |||
if args.type == 'function' then | |||
line = language..' uses the '..languageSymbols[language][args.type]..' symbol to call a function.' | |||
elseif args.type == 'variable' then | |||
line = language..' uses the '..languageSymbols[language][args.type]..' symbol to get or set a variable.' | |||
elseif args.type == 'method' then | |||
line = language..' uses the '..languageSymbols[language][args.type]..' symbol to call a method.' | |||
elseif args.type == 'property' then | |||
line = language..' uses the '..languageSymbols[language][args.type]..' symbol to get or set a property.' | |||
end | |||
table.insert(out, "<br>"..line) | |||
end | |||
end | end | ||
return table.concat(out, "") | |||
end | end | ||
Line 837: | Line 1,014: | ||
function p.formatType(type, frame) | function p.formatType(type, frame) | ||
return p. | return "<span style='font-family: \"Source Code Pro\", monospace; color: "..p.getTypeRgb()..";\"'>"..type.."</span>" | ||
end | |||
function p.formatName(name, frame) | |||
return "<span style='font-family: \"Source Code Pro\", monospace; color: "..p.getNameRgb()..";\"'>"..name.."</span>" | |||
end | end | ||
function p.formatSource(type, frame) | function p.formatSource(type, frame) | ||
return frame:preprocess('< | return frame:preprocess('<syntaxhighlight>'..type..'</syntaxhighlight>') | ||
end | end | ||
Line 975: | Line 1,156: | ||
function p.properCase(text) | function p.properCase(text) | ||
return text:sub(1,1):upper()..text:sub(2):lower() | return text:sub(1,1):upper()..text:sub(2):lower() | ||
end | |||
function p.lowerFirstCharCase(text) | |||
return text:sub(1,1):lower()..text:sub(2) | |||
end | end | ||
Latest revision as of 22:39, 6 January 2024
Documentation for this module may be created at Module:ScriptItem/doc
local p = {} -- settings p.categoryItems = { -- Category Name = table. (Fully resolved item name(s), case-sensitive.) (Event names must start with a capital letter "O", to match the dumpdoc XML.) ['Audio'] = {'gta.addOneOffSound', 'gta.playFrontEndSound', 'gta.playSuspectLastSeen'}, ['Camera'] = {'gta.fading'}, ['Chatbox'] = {'message', 'messageClient', 'messageAllExcept', 'setChatWindowEnabled', 'OnChatOutput'}, ['Cursor'] = {'gta.getMouseSpeed'}, ['CustomText'] = {'gta.setCustomText', 'gta.setCustomText', 'gta.clearCustomText', 'gta.printBig'}, ['Drawing'] = {'gta.drawRectangle'}, ['Effect'] = {'gta.addParticleEffect', 'addParticleEffect', 'gta.addMovingParticleEffect', 'addMovingParticleEffect', 'gta.createSingleParticle', 'createSingleParticle'}, ['Font'] = {'font.render'}, ['GarbageCollection'] = {'collectAllGarbage'}, ['Game'] = {'gta.game', 'gta.standardControls', 'gta.gameSpeed', 'gta.loadDFF', 'gta.loadTXD', 'gta.loadCOL'}, ['GameStat'] = {'gta.setGameStat', 'gta.getGameStat'}, ['GUI'] = {'OnGUIClick'}, ['Key'] = {'isScancodePressed', 'OnCharacter'}, ['KillFrenzy'] = {'gta.startKillFrenzy'}, ['Message'] = {'gta.clearMessages', 'gta.smallMessage', 'gta.bigMessage', 'gta.pagerMessage'}, ['Miscellaneous'] = {'platform', 'toColour', 'gta.tickCount', 'getRandomSkin', 'gta.getRandomSkin', 'gta.processLineOfSight', 'processLineOfSight', 'gta.setIsland', 'gta.setDefaultInteriors'}, ['Network'] = {'isConnected', 'isConnecting', 'connect', 'disconnect', 'triggerNetworkEvent', 'OnDisconnect'}, ['Path'] = {'gta.trafficDensity', 'gta.setTrafficEnabled', 'setTrafficEnabled', 'gta.setCiviliansEnabled', 'setCiviliansEnabled'}, ['Ped'] = {'gta.tommyFatness'}, ['Radio'] = {'gta.setRadioChannel', 'gta.forceRadioChannel'}, ['Reflection'] = {'exportFunction', 'setErrorMode'}, ['Renderware'] = {'gta.rwRenderStateSet'}, ['SaveGame'] = {'gta.saveGame'}, ['Screen'] = {'gta.aspectRatio', 'gta.width', 'gta.height'}, ['Script'] = {'gta.terminateScript', 'gta.getActiveScripts', 'gta.scriptCommand'}, ['Timer'] = {'setImmediate', 'clearImmediate', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'}, ['Weather'] = {'snowing', 'forceSnowing'}, ['Window'] = {'OnFocus', 'OnLostFocus'}, ['World'] = {'gta.ssvBridgeEnabled', 'gta.planesEnabled', 'gta.trainsEnabled', 'setPlanesEnabled', 'setTrainsEnabled', 'world', 'gta.findGroundZForCoord', 'findGroundZForCoord', 'gta.setTrainsEnabled', 'gta.setPlanesEnabled'} } p.categoryWords = { -- Category Names. (String(s) to look for in an item name, case-INsensitive.) 'Blip', 'Building', 'Camera', 'Chatbox', 'Cheat', 'Client', 'Command', 'Cursor', 'Debug', 'Dodo', 'Element', 'Entity', 'Event', 'File', 'Font', 'Garage', 'HTTP', 'HUD', 'Key', 'Mission', 'Mouse', 'NetFlags', 'Network', 'Object', 'Pause', 'Ped', 'Pickup', 'Player', 'Process', 'Render', 'Resource', 'Screen', 'Socket', 'Sphere', 'Time', 'Vehicle', 'Weather', 'World' } -- entry point function p.main(frame) local args = p.getArgs(frame) if args.type == 'variable' then return p.showVariablePage(frame) elseif args.type == 'function' then return p.showFunctionPage(frame) elseif args.type == 'property' then return p.showPropertyPage(frame) elseif args.type == 'method' then return p.showMethodPage(frame) elseif args.type == 'event' then return p.showEventPage(frame) else return "This page has been documented incorrectly, '''type''' is missing." end end -- item page types function p.showVariablePage(frame) return p.showPage(frame, { "Value" }) end function p.showFunctionPage(frame) return p.showPage(frame, { "Parameters", "Return", "Callbacks" }) end function p.showPropertyPage(frame) return p.showPage(frame, { "Value" }) end function p.showMethodPage(frame) return p.showPage(frame, { "Parameters", "Return", "Callbacks" }) end function p.showEventPage(frame) return p.showPage(frame, { "Parameters", "Attributes" }) end -- item page function p.showPage(frame, parts) local args = p.getArgs(frame) if args.type ~= 'event' then table.insert(parts, "Types") end --table.insert(parts, "Symbols") local lines = p.getPageTopLines(frame) for i,part in ipairs({"Notes", "Examples", "Compatibility", "Related"}) do table.insert(parts, part) end for i,part in ipairs(parts) do local data = p[part:lower() == 'return' and 'returns' or part:lower()](frame) if data and #data > 0 then if part == 'Settable' then part = args.readonly == 'true' and 'Read-Only' or 'Read and Set' end table.insert(lines, '== '..part..' ==') table.insert(lines, data) end end return table.concat(lines, "\n") end function p.getPageTopLines(frame) local lines = {} table.insert(lines, frame:preprocess("{{DISPLAYTITLE:"..p.getDisplayedName(frame).."}}")) -- Added for discord embed styling --table.insert(lines, "<meta content='"..p.getDisplayedName(frame).."' property='og:title' />")) --table.insert(lines, "<meta content='"..p.description(frame).."' property='og:description' />")) --table.insert(lines, "<meta content='#04C765' data-react-helmet='true' name='theme-color' />")) table.insert(lines, "__NOTOC__"..p.getPageTopBoxes(frame).."\n") table.insert(lines, "<div style='margin-top: 20px;'>Available since "..p.since(frame).."</div>\n") table.insert(lines, "<div style='margin-top: 6px;'>\n"..p.syntax(frame).."</div>\n") table.insert(lines, "<div style='margin-top: 20px;'>\n"..p.description(frame).."</div>\n") return lines end function p.getPageTopBoxes(frame) local args = p.getArgs(frame) local topBoxes = { "type", "endpoint", "games", "online" } if args.type == 'variable' or args.type == 'property' then table.insert(topBoxes, "settable") elseif args.type == 'event' then table.insert(topBoxes, "cancellable") end local outBoxes = {} for i,topBox in ipairs(topBoxes) do table.insert(outBoxes, p[topBox.."Box"](frame)) end return table.concat(outBoxes, ' ').."<br>" end -- template arguments function p.getArgs(frame) if p.argsCache then return p.argsCache else local args = frame:getParent().args p.copyOldToNewForTemplateArguments(frame, args) p.copyNonIndexedToIndexedTemplateArguments(frame, args) p.populateTypeSpecificTemplateArguments(frame, args) p.populateDefaultTemplateArguments(frame, args) p.argsCache = args return args end end function p.copyOldToNewForTemplateArguments(frame, args) if args.parameters then args.syntax = args.parameters end if args.parametersSS then args.syntaxSS = args.parametersSS end if args.parametersCS then args.syntaxCS = args.parametersCS end if args.callbackParameters then args.callbackSyntax = args.callbackParameters end if args.callbackParametersSS then args.callbackSyntaxSS = args.callbackParametersSS end if args.callbackParametersCS then args.callbackSyntaxCS = args.callbackParametersCS end if args.type == 'event' then if args.callbackParameters then args.syntax = args.callbackParameters end if args.callbackParametersSS then args.syntaxSS = args.callbackParametersSS end if args.callbackParametersCS then args.syntaxCS = args.callbackParametersCS end end if args.returnType or args.returnTypes then local returnType = args.returnType and args.returnType or args.returnTypes if args.returnInfo then args.return1 = returnType.." "..args.returnInfo args.value = returnType.." "..args.returnInfo else args.return1 = returnType args.value = returnType end end if args.usage then args.description = args.usage end if args.notes then local notes = p.splitLines(args.notes) for i,note in ipairs(notes) do args['note'..i] = note end end local exampleKeys = { 'example', 'exampleSS', 'exampleCS', 'exampleJS', 'exampleLua', 'exampleSquirrel', 'exampleJSSS', 'exampleJSCS', 'exampleLuaSS', 'exampleLuaCS', 'exampleSquirrelSS', 'exampleSquirrelCS' } for i,exampleKey in ipairs(exampleKeys) do if args[exampleKey] then local examples = p.split(args[exampleKey], '<br>') for i,example in ipairs(examples) do args[exampleKey..i] = example end end end if args.bcName and args.bcMaxVersion then args.previous1 = args.bcName.." "..args.bcMaxVersion end end function p.copyNonIndexedToIndexedTemplateArguments(frame, args) if args.description then args.description1 = args.description end end function p.populateTypeSpecificTemplateArguments(frame, args) if args.type == 'variable' or args.type == 'property' then if args.value then local tokens = p.split(args.value, ' ') local type = tokens[1] local name if args.type == 'property' then name = args.class.."."..args.name else name = args.name end args.syntax = type.." "..name end end end function p.populateDefaultTemplateArguments(frame, args) if not args.since then args.since = "1.0.0 1.0.0" end if args.syntax and args.syntax:lower() == "void" then args.parameter1 = "void" end end -- item top boxes function p.typeBox(frame) local args = p.getArgs(frame) local typeText = p.getType(args.type) return p.loadTemplate(frame, 'GreenInformationBox', {typeText,id='type'}); end function p.endpointBox(frame) local args = p.getArgs(frame) local endpointText, isShared = p.getEndpoint(args.endpoint) if isShared then return p.loadTemplate(frame, 'GreenInformationBox', {endpointText,id='endpoint'}); else return p.loadTemplate(frame, 'RedInformationBox', {endpointText,id='endpoint'}); end end function p.gamesBox(frame) local args = p.getArgs(frame) local gamesText = p.getGames(args.games) if gamesText == "All Games" then return p.loadTemplate(frame, 'GreenInformationBox', {table.concat({ p.loadTemplate(frame, 'icon-iii'), p.loadTemplate(frame, 'icon-vc'), p.loadTemplate(frame, 'icon-sa'), p.loadTemplate(frame, 'icon-iv') }, ' '), id='games'}) else local games = { 'iii', 'vc', 'sa', 'iv' } local out = {} for i,game in ipairs(games) do if gamesText:lower():find(game) then table.insert(out, p.loadTemplate(frame, 'icon-'..game, {})) end end return p.loadTemplate(frame, 'RedInformationBox', {table.concat(out, ' '), id='games'}) end end function p.onlineBox(frame) local args = p.getArgs(frame) if args.sp == 'true' or args.online == 'false' then return p.loadTemplate(frame, 'RedInformationBox', {'Offline Only',id='online'}); elseif args.sp == 'false' or args.offline == 'false' then return p.loadTemplate(frame, 'RedInformationBox', {'Online Only',id='online'}); else return p.loadTemplate(frame, 'GreenInformationBox', {'Online and Offline',id='online'}); end end function p.settableBox(frame) local args = p.getArgs(frame) if args.readonly == 'true' then return p.loadTemplate(frame, 'RedInformationBox', {'Read-Only',id='settable'}); else return p.loadTemplate(frame, 'GreenInformationBox', {'Read and Set',id='settable'}); end end function p.cancellableBox(frame) local args = p.getArgs(frame) if p.isCancellable(frame)then return p.loadTemplate(frame, 'GreenInformationBox', {'Cancellable',id='cancellable'}); else return p.loadTemplate(frame, 'RedInformationBox', {'Not Cancellable',id='cancellable'}); end end -- item parts function p.since(frame) local args = p.getArgs(frame) if not args.since then return p.documentationMissing(frame, "Available since") else local endpointVersions = p.getEndpointVersions(args.since, args.endpoint) if #endpointVersions == 2 then return "'''Server "..endpointVersions[1].."''', '''Client "..endpointVersions[2].."'''" else if args.endpoint == 'server' then return "'''Server "..endpointVersions[1].."'''" elseif args.endpoint == 'client' then return "'''Client "..endpointVersions[1].."'''" else return p.documentationMissing(frame, "Available since (Both server and client version is needed for shared items)") end end end end function p.syntax(frame) local args = p.getArgs(frame) if args.syntax then return p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntax),id='syntax'}) end if args.syntaxSS and args.syntaxCS then local rows = {} rows[1] = { "'''Server:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntaxSS),id='syntaxss'}) } rows[2] = { "'''Client:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.syntaxCS),id='syntaxcs'}) } return p.table(false, rows, { 100 }, false) end return p.documentationMissing(frame, "Syntax") end function p.description(frame) local args = p.getArgs(frame) local entries = p.getIndexedArgs(frame, 'description') local startTextFirstLine = "The <span style=\"font-family: 'Source Code Pro', monospace;\">"..p.getDisplayedNameColoured(frame).."</span> [[HowTo/Functions|"..args.type.."]] is "..(args.type == "event" and "invoked when" or "used to").." " for i,entry in ipairs(entries) do if i == 1 then entry = startTextFirstLine..entry end entries[i] = p.formatDescription(entry) end return table.concat(entries, '<br>') end function p.parameters(frame) local args = p.getArgs(frame) local entries = p.getIndexedArgs(frame, 'parameter') local rows = {} local isEvent = args.type == 'event' if isEvent and args.syntax and args.syntax:lower() == 'event event' then elseif #entries == 0 then return p.documentationMissing(frame, "Parameters") elseif entries[1] == "void" then local headers = nil local rows = { { p.formatType("void", frame), "This "..args.type.." doesn't take any parameters." } } local widths = { 120, 400 } return p.table(headers, rows, widths, 'wikitable-returns wikitable') else for i,arg in ipairs(entries) do local tokens = p.split(arg, ' ') local isOptional = tokens[3] == 'optional' local defaultValue = isOptional and "<span style='font-family: \"Source Code Pro\", monospace;'>"..tokens[4].."</span>" or "n/a" local description = p.formatDescription(table.concat(tokens, ' ', isOptional and 5 or 3)) if isEvent then rows[i] = { (i + 1)..") ", p.formatType(tokens[1], frame), p.formatName(tokens[2], frame), description } else rows[i] = { i..") ", p.formatType(tokens[1], frame), p.formatName(tokens[2], frame), (isOptional and ("Optional, defaults to "..defaultValue..". ") or "")..description } end end end if isEvent then table.insert(rows, 1, { "1) ", p.formatType("Event", frame), p.formatName("event", frame), "The event object for this event." }) end local headers, widths if isEvent then headers = nil--{ "Type", "Name", "Description" } widths = { 30, 80, 110, 400 } else headers = nil--{ "Type", "Name", "Presence", "Default Value", "Description" } widths = { 30, 80, 110, 400 } end return p.table(headers, rows, widths, 'wikitable-parameters wikitable') end function p.returns(frame) local args = p.getArgs(frame) local text = "" local entries local rows local headers local widths local isVoidReturn = false rows = {} entries = p.getIndexedArgs(frame, 'return') if #entries == 0 then text = text..p.documentationMissing(frame, "Returns").."<br><br>" else for i,arg in ipairs(entries) do local tokens = p.split(arg, ' ') local type = tokens[1] type = p.standardizeNullType(type) local description if type:lower() == "void" then isVoidReturn = true description = "This "..args.type.." doesn't return a value." elseif tokens[2] then description = p.formatDescription(table.concat(tokens, ' ', 2)) else description = p.documentationMissing(frame, "Description for return value") end rows[i] = { p.formatType(tokens[1], frame), description } end headers = nil-- { "Type", "Description" } widths = { 120, 400 } text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable') end --[[ -- commented out as failure returns are not currently implemented in GTAC. if not isVoidReturn then rows = {} entries = p.getIndexedArgs(frame, 'returnFail') text = text.."'''Failure Return:'''\n\n" if #entries == 0 then text = text..p.documentationMissing(frame, "Failure returns") else for i,arg in ipairs(entries) do local tokens = p.split(arg, ' ') local type = tokens[1] type = p.standardizeNullType(type) local value if type:lower() == 'void' then value = "n/a" elseif tokens[2] then value = p.formatSource(table.concat(tokens, ' ', 2), frame) else value = p.formatSource(p.documentationMissing(frame, "Description for failure return value"), frame) end rows[i] = { p.formatType(tokens[1], frame), value } end headers = nil--{ "Type", "Value" } widths = { 120, 400 } text = text..p.table(headers, rows, widths, 'wikitable-returns wikitable') end end ]] return text end function p.callbacks(frame) local args = p.getArgs(frame) local suffixes = { { '', '' }, { 'SS', 'Server-Side Callbacks' }, { 'CS', 'Client-Side Callbacks' } } local html = {} for i3,suffixData in ipairs(suffixes) do local suffix = suffixData[1] local parameters = p.getIndexedArgs(frame, 'parameter') for i=1, #parameters do local callbackSyntax = args['callback'..i..'Syntax'..suffix] local callbackText = args['callback'..i..'Text'..suffix] local callbackNParameters = p.getIndexedArgs(frame, 'callback'..i..'Parameter'..suffix) if #callbackNParameters > 0 then if suffixData[1] ~= '' then table.insert(html, "'''"..suffixData[2].."'''") end local parameterTokens = p.split(parameters[i], ' ') local rows = {} if #parameterTokens > 0 then local syntaxLine = parameterTokens[1]..' '..parameterTokens[2]..'('..callbackSyntax..')' syntaxLine = p.loadTemplate(frame, 'CodeSyntax', {syntaxLine}) table.insert(html, syntaxLine) end if callbackText and #callbackText > 0 then table.insert(html, callbackText) end for i2,callbackNParameter in ipairs(callbackNParameters) do local callbackTokens = p.split(callbackNParameter, ' ') local parameterType = callbackTokens[1] local parameterName = callbackTokens[2] local description = p.formatDescription(table.concat(callbackTokens, ' ', 3)) rows[i2] = { i2..') ', p.formatType(parameterType, frame), p.formatName(parameterName, frame), description } end local headers, widths headers = nil--{ "Type", "Name", "Description" } widths = { 30, 80, 110, 400 } local table2 = "\n"..p.table(headers, rows, widths, 'wikitable-callback wikitable') table.insert(html, table2) if i ~= #parameters then table.insert(html, "<br>") end end end end if args.callbackSyntax then table.concat(html, p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntax, true),id='callbacks'})) end if args.callbackSyntaxSS and args.callbackSyntaxCS then local rows = {} rows[1] = { "'''Server:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntaxSS, true),id='callbacks'}) } rows[2] = { "'''Client:'''", p.loadTemplate(frame, 'CodeSyntax', {p.buildSyntax(frame, args.callbackSyntaxCS, true),id='callbacks'}) } table.concat(html, p.table(false, rows, { 100 }, false, 'wikitable-callback wikitable')) end return #html > 0 and table.concat(html, '') or false end function p.attributes(frame) local args = p.getArgs(frame) local headers = nil--{ "Type", "Description" } local rows = {} if p.isCancellable(frame) then rows[1] = { 'cancellable', 'This '..args.type..' can be cancelled, by using [[event.preventDefault|event.preventDefault]].' } else rows[1] = { p.formatType('const', frame), 'This '..args.type..' cannot be cancelled.' } end local widths = { 120, 400 } return p.table(headers, rows, widths, 'wikitable-returns wikitable') end function p.value(frame) local args = p.getArgs(frame) if not args.value then return p.documentationMissing(frame, "Value type and description") end local arg = args.value local tokens = p.split(arg, ' ') local description = p.formatDescription(table.concat(tokens, ' ', 2)) local headers = nil--{ "Type", "Description" } local rows = {} rows[1] = { p.formatType(tokens[1], frame), description } if args.readonly == 'true' then rows[2] = { p.formatType('readonly', frame), 'This '..args.type..' cannot be changed.' } else rows[2] = { 'read/set', 'This '..args.type..' can be changed, as well as read.' } end local widths = { 120, 400 } return p.table(headers, rows, widths, 'wikitable-returns wikitable') end function p.settable(frame) local args = p.getArgs(frame) if args.readonly == 'true' then return "This "..args.type.." is read-only." else return "This "..args.type.." can be read and set." end end function p.types(frame) local args = p.getArgs(frame) return p.getTypesText(frame, args.class) end function p.symbols(frame) local args = p.getArgs(frame) return p.getSymbolsText(frame, args.class) end function p.notes(frame) local args = p.getArgs(frame) local entries = p.getIndexedArgs(frame, 'note') if #entries == 0 then return "There aren't any notes for this "..args.type.."." end for i,entry in ipairs(entries) do entries[i] = p.dot(entry) end return "* "..table.concat(entries, "\n* ") end function p.examples(frame) local args = p.getArgs(frame) local data = { { "example", "" }, { "exampleSS", "Server-Side" }, { "exampleCS", "Client-Side" }, { "exampleJS", "JavaScript" }, { "exampleLua", "Lua" }, { "exampleSquirrel", "Squirrel" }, { "exampleJSSS", "JavaScript - Server-Side" }, { "exampleJSCS", "JavaScript - Client-Side" }, { "exampleLuaSS", "Lua - Server-Side" }, { "exampleLuaCS", "Lua - Client-Side" }, { "exampleSquirrelSS", "Squirrel - Server-Side" }, { "exampleSquirrelCS", "Squirrel - Client-Side" } } local examples = {} local exampleIndex = 1 for i,data2 in ipairs(data) do local entries = p.getIndexedArgs(frame, data2[1]) for i2, entry in ipairs(entries) do local entry = "'''Example "..exampleIndex.." - "..data2[2]..":'''<br>"..p.loadTemplate(frame, 'CodeSyntax', {entry,id='example_'..exampleIndex}) table.insert(examples, entry) exampleIndex = exampleIndex + 1 end end if #examples == 0 then return "There aren't any examples for this "..args.type.."." end return table.concat(examples, "<br>") end function p.compatibility(frame) local args = p.getArgs(frame) local entries1 = p.getIndexedArgs(frame, 'previous') local entries2 = p.getIndexedArgs(frame, 'compat') if #entries1 == 0 and #entries2 == 0 then return "There isn't any compatibility information for this "..args.type.."." else local entriesOut = {} for i,arg in ipairs(entries1) do local versionsText, tokens = p.getVersionsText(arg, args.endpoint, 2) entriesOut[i] = "This "..args.type.." was previously named <code>"..tokens[1].."</code> in "..versionsText.."." end local offset = #entriesOut for i,arg in ipairs(entries2) do entriesOut[i + offset] = p.dot(arg) end return "* "..table.concat(entriesOut, "\n* ") end end function p.related(frame) local args = p.getArgs(frame) local categoryTitle = p.getItemCategory(frame) if categoryTitle and categoryTitle:len() > 0 then local shared = args.endpoint:lower() == 'shared' local server = args.endpoint:lower() == 'shared' or args.endpoint:lower() == 'server' local client = args.endpoint:lower() == 'shared' or args.endpoint:lower() == 'client' local pageName = args.type:lower() == 'event' and 'Event' or 'Function' local parts = {} local name if args.type == 'property' then name = args.class.."."..args.name else name = args.name end if server then local title = 'Server/'..pageName..'s/'..categoryTitle local t = p.loadTemplate(frame, title, args) --t = p.remove(t, "[["..name.."|"..name.."]]<br>\n") --[[ t = p.replace(t, " ", " "); t = p.remove(t, "\t"); t = p.remove(t, "\r"); t = p.remove(t, "\n"); t = p.remove(t, "<a class=\"mw-selflink selflink\">"..name.."</a><br />") ]] table.insert(parts, "'''Server Related'''<br><br>"..t) end if client then local title = 'Client/'..pageName..'s/'..categoryTitle local t = p.loadTemplate(frame, title, args) --t = p.remove(t, "[["..name.."|"..name.."]]<br>\n") --[[ t = p.replace(t, " ", " "); t = p.remove(t, "\t"); t = p.remove(t, "\r"); t = p.remove(t, "\n"); t = p.remove(t, "<a class=\"mw-selflink selflink\">"..name.."</a><br />") ]] table.insert(parts, "'''Client Related'''<br><br>"..t) end return table.concat(parts, '<br><br>') else return '' end end -- item category function p.getItemCategory(frame) local args = p.getArgs(frame) local resolvedNameLower = p.getDisplayedName(frame):lower() for categoryTitle,categoryData in pairs(p.categoryItems) do for i2,resolvedItemName in ipairs(categoryData) do if resolvedNameLower == resolvedItemName:lower() then return categoryTitle end end end for i,categoryTitle in ipairs(p.categoryWords) do if resolvedNameLower:find(categoryTitle:lower(), 1, true) then return categoryTitle end end return false end -- item part utility function p.getType(text) local finds = { "variable", "function", "property", "method", "event", "define" } local replaces = { "Variable", "Function", "Property", "Method", "Event", "Define" } local defaults = {} return p.findText(text, finds, replaces, defaults, "'''undocumented type'''") end function p.getGames(text) local finds = { "iii", "vc", "sa", "iv", "ug" } local replaces = { "GTA III", "GTA VC", "GTA SA", "GTA IV", "GTA UG" } local defaults = { "all", "all games" } return p.findText(text, finds, replaces, defaults, "All Games") end function p.getEndpoint(text) local finds = { "shared", "server", "client" } local replaces = { "Server and Client", "Server Only", "Client Only" } local defaults = {} local result = p.findText(text, finds, replaces, defaults, "'''undocumented endpoint'''") local isShared = result == replaces[1] return result, isShared end function p.getDisplayedName(frame) local args = p.getArgs(frame) if p.isOOP(frame) then return p.lowerFirstCharCase(args.class).."."..args.name else return args.name end end function p.getTypeRgb() return '#009106' end function p.getNameRgb() return '#0645ad' end function p.getDisplayedNameColoured(frame) local typeRgb = p.getTypeRgb() local nameRgb = p.getNameRgb() local args = p.getArgs(frame) if p.isOOP(frame) then return "<span style='color:"..typeRgb..";'>"..p.lowerFirstCharCase(args.class).."</span>.<span style='color:"..nameRgb.."';>"..args.name.."</span>" else return "<span style='color:"..nameRgb.."';>"..args.name.."</span>" end end function p.getSuccessReturnTypes(frame) local entries = p.getIndexedArgs(frame, 'return') if #entries == 0 then return "unknown" end for i,entry in ipairs(entries) do local tokens = p.split(entry, ' ') entries[i] = tokens[1] end return table.concat(entries, ", ") end function p.isOOP(frame) local args = p.getArgs(frame) return args.type == "property" or args.type == "method" end function p.warning(frame, text) return p.loadTemplate(frame, 'BlueInformationBox', {text})..'\n' end function p.documentationMissing(frame, text) return p.warning(frame, "Documentation Missing: "..text) end function p.buildSyntax(frame, parameters, isCallback) if isCallback == nil then isCallback = false; end local args = p.getArgs(frame) if not isCallback and (args.type == 'variable' or args.type == 'property') then return p.getSuccessReturnTypes(frame).." "..p.getDisplayedName(frame) elseif isCallback or args.type == 'event' then return "function("..parameters..")" else return p.getSuccessReturnTypes(frame).." "..p.getDisplayedName(frame).."("..parameters..")" end end function p.getTypesText(frame, baseType) local args = p.getArgs(frame) local derivedTypes = { ped = {'Player'}, physical = {'Object', 'Ped', 'Vehicle', 'Player'}, entity = {'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Player'}, element = {'Blip', 'Entity', 'Marker', 'Building', 'Physical', 'Object', 'Ped', 'Vehicle', 'Player'}, vehicle = {'Train'}, event = {'CancellableEvent', 'KeyEvent'}, surface = {'RenderTarget', 'Texture'} } local serverTypes = {} local sharedTypes = { 'Building', 'Client', 'Effect', 'Event', 'Timer', 'ReflectedFunction', 'Resource', 'Stream', 'Vec2', 'Vec3', 'Matrix4x4', 'Element', 'Blip', 'Pickup', 'Entity', 'Physical','Vehicle', 'Train', 'XmlDocument', 'XmlElement', 'CancellableEvent', 'KeyEvent', 'Marker', 'Object', 'Ped', 'Player' } local out = {} local getTypeSide = function(type) for i2,type2 in ipairs(serverTypes) do if type:lower() == type2:lower() then return 'server' end end for i2,type2 in ipairs(sharedTypes) do if type:lower() == type2:lower() then return 'shared' end end return 'client' end if baseType then local baseTypeLower = baseType:lower() local allTypes if derivedTypes[baseTypeLower] then allTypes = p.copyTable(derivedTypes[baseTypeLower]) table.insert(allTypes, 1, baseType) else allTypes = { baseType } end local types = {} for i,type in ipairs(allTypes) do types[i] = type end p.sortTable(types) for i,type in ipairs(types) do types[i] = p.loadTemplate(frame, 'Side', {[getTypeSide(type)]='1'}).." ".."<span style=\"font-family: 'Source Code Pro', monospace;\">"..type.."</span>" end --table.insert(out, "<div style='margin-top: 20px;'></div>") table.insert(out, "\n"..table.concat(types, "<br>")) end return table.concat(out, "") end function p.getSymbolsText(frame, baseType) local args = p.getArgs(frame) local out = {} local rows = {} if args.type == 'function' or args.type == 'variable' then local parts = p.split(p.getDisplayedName(frame), ".") for i=1,(#parts)-1,1 do rows[i] = {} rows[i][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[i].."</span>" rows[i][2] = 'Namespace' rows[i][3] = i == 1 and 'Global' or 'Namespace: '..parts[i-1] rows[i][4] = i == 1 and parts[i]..' is a namespace, which exists in the global namespace.' or parts[i]..' is a namespace, which exists in the '..parts[i-1]..' namespace.' end rows[#parts] = {} rows[#parts][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[#parts].."</span>" rows[#parts][2] = p.properCase(args.type) rows[#parts][3] = #parts == 1 and 'Global' or 'Namespace: '..parts[#parts-1] rows[#parts][4] = #parts == 1 and parts[1]..' is a '..p.properCase(args.type)..', which exists in the global namespace.' or parts[#parts]..' is a '..p.properCase(args.type)..', which exists in the '..parts[#parts-1]..' namespace.' elseif args.type == 'method' or args.type == 'property' then local parts = p.split(p.getDisplayedName(frame), ".") rows[1] = {} rows[1][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[1].."</span>" rows[1][2] = 'Object' rows[1][3] = 'n/a' rows[1][4] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[1].."</span>"..' is an object.' rows[2] = {} rows[2][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[2].."</span>" rows[2][2] = p.properCase(args.type) rows[2][3] = #parts == 1 and 'Global' or 'Namespace: '..parts[#parts-1] rows[2][4] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..parts[2].."</span>"..' is a '..p.properCase(args.type)..', which is used on objects of type '..parts[1] elseif args.type == 'event' then rows[1] = {} rows[1][1] = "<span style=\"font-family: 'Source Code Pro', monospace; color: "..p.getNameRgb()..";\">"..p.getDisplayedName(frame).."</span>" rows[1][2] = 'String' rows[1][3] = 'n/a' rows[1][4] = 'Events are referenced by name. Event names use data type String.' end --table.insert(out, "<div style='margin-top: 20px;'></div>") local headers = { 'Symbol Name', 'Symbol Type', 'Container', 'Description' } table.insert(out, "\n"..p.table(headers, rows, { 120, 120, 400 }, false)) if args.type ~= 'event' then local languages = { 'JS', 'Lua', 'Squirrel' } local languageSymbols = { ['JS'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'dot', ['property'] = 'dot' }, ['Lua'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'colon', ['property'] = 'dot' }, ['Squirrel'] = { ['function'] = 'dot', ['variable'] = 'dot', ['method'] = 'dot', ['property'] = 'dot' } } for i,language in ipairs(languages) do local line if args.type == 'function' then line = language..' uses the '..languageSymbols[language][args.type]..' symbol to call a function.' elseif args.type == 'variable' then line = language..' uses the '..languageSymbols[language][args.type]..' symbol to get or set a variable.' elseif args.type == 'method' then line = language..' uses the '..languageSymbols[language][args.type]..' symbol to call a method.' elseif args.type == 'property' then line = language..' uses the '..languageSymbols[language][args.type]..' symbol to get or set a property.' end table.insert(out, "<br>"..line) end end return table.concat(out, "") end function p.isCancellable(frame) local args = p.getArgs(frame) return (args.cancellable and args.cancellable == 'true') or (args.cancelable and args.cancelable == 'true') end function p.formatType(type, frame) return "<span style='font-family: \"Source Code Pro\", monospace; color: "..p.getTypeRgb()..";\"'>"..type.."</span>" end function p.formatName(name, frame) return "<span style='font-family: \"Source Code Pro\", monospace; color: "..p.getNameRgb()..";\"'>"..name.."</span>" end function p.formatSource(type, frame) return frame:preprocess('<syntaxhighlight>'..type..'</syntaxhighlight>') end function p.formatCode(code) return "<code>"..code.."</code>" end function p.formatDescription(description) description = p.capital(description) description = p.dot(description) return description end function p.standardizeNullType(type) type = type:lower() if type == 'void' or type == 'null' or type == 'undefined' or type == 'n/a' then return 'void' else return type end end -- general utility function p.split(str, sep, limit) if not sep or sep == "" then return false end if not str then return false end limit = limit or math.huge if limit == 0 or limit == 1 then return {str}, 1 end local r = {} local n, init = 0, 1 while true do local s,e = str:find(sep, init, true) if not s then break end r[#r+1] = str:sub(init, s - 1) init = e + 1 n = n + 1 if n == limit - 1 then break end end if init <= str:len() then r[#r+1] = str:sub(init) else r[#r+1] = "" end n = n + 1 if limit < 0 then for i=n, n + limit + 1, -1 do r[i] = nil end n = n + limit end return r, n end function p.splitLines(text) text = p.remove(text, "\n") text = p.remove(text, "\r") return p.split(text, "<br>") end function p.remove(text, remove) return p.replace(text, remove, "") end function p.replace(text, find, replace) return text:gsub(find, replace) end function p.getIndexedArgs(frame, name) local args = p.getArgs(frame) local i = 1 local out = {} while args[name..i] do out[i] = args[name..i] i = i + 1 end return out end function p.loadTemplate(frame, title, args) return frame:expandTemplate{ title = title, args = args } end function p.getEndpointVersions(arg, endpoint, start) if not start then start = 1 end local tokens = p.split(arg, ' ') local endpointVersions = {} if endpoint == 'shared' then if tokens[start+1] then endpointVersions[1] = tokens[start] endpointVersions[2] = tokens[start+1] else endpointVersions[1] = tokens[start] end elseif endpoint == 'server' then endpointVersions[1] = tokens[start] elseif endpoint == 'client' then endpointVersions[1] = tokens[start] end return endpointVersions, tokens end function p.getVersionsText(arg, endpoint, start) if not start then start = 1 end local tokens = p.split(arg, ' ') local text if endpoint == 'shared' then if tokens[start+1] then text = "server version "..tokens[start].." and client version "..tokens[start+1] else text = "version "..tokens[start] end elseif endpoint == 'server' then text = "server version "..tokens[start] elseif endpoint == 'client' then text = "client version "..tokens[start] end return text, tokens end function p.properCase(text) return text:sub(1,1):upper()..text:sub(2):lower() end function p.lowerFirstCharCase(text) return text:sub(1,1):lower()..text:sub(2) end function p.findText(text, finds, replaces, defaults, default) if not text then return default end local textLower = text:lower() for i,default2 in ipairs(defaults) do if textLower == default2 then return default end end local items = {} for i,find in ipairs(finds) do if textLower:find(find, 1, true) then table.insert(items, replaces[i]) end end return p.getListText(items) end function p.getListText(items) local count = #items if count == 1 then return items[1] elseif count == 2 then return items[1].." and "..items[2] else return table.concat(items, ", ", 1, count - 1).." and "..items[count] end end function p.dot(text) local i = #text while i > 0 and text:sub(i, i) == "." do i = i - 1 end return text:sub(1,i).."." end function p.capital(text) return text:sub(1,1):upper()..text:sub(2) end function p.copyTable(t) local out = {} for k,v in pairs(t) do out[k] = v end return out end function p.sortTable(t) table.sort(t, function(a,b) return a:lower() < b:lower() end) end function p.table(headers, rows, widths, tableCssClass) if tableCssClass == nil then tableCssClass = 'wikitable' end rows = p.copyTable(rows) if not widths then widths = {} end if headers then headers = p.copyTable(headers) for i,header in ipairs(headers) do local width = widths[i] if width and width > 0 then headers[i] = "id='th_"..i.."' style='text-align:left;"..(i==#headers and 'min-width' or 'width')..":"..width.."px;'| "..header end end else for i,cell in ipairs(rows[1]) do local width = widths[i] if width and width > 0 then rows[1][i] = "id='td_"..i.."' style='text-align:left;"..(i==#rows[1] and 'min-width' or 'width')..":"..width.."px;'| "..cell end end end for i,row in ipairs(rows) do rows[i] = '|'..table.concat(row, '\n|') end return '{|'..(tableCssClass and ' class="'..tableCssClass..'"' or '')..(headers and " id='headers' " and '\n!'..table.concat(headers, '\n!')..'\n|-' or '')..'\n'..table.concat(rows, '\n|-\n')..'\n|}' end -- return the module return p