DependencyGraph outputs a module dependency graph of this wiki's modules using the DOT language.
Requires Extension:DynamicPageList enabled on your wiki.
Recommended layout algorithms for rendering resultant DOT file:
fdp
/sfdp
- useful for viewing entire codebase w/ clustering of module familiescirco
- circular layout, useful for finding modules/submodules with the fewest dependencies
See https://www.rdocumentation.org/packages/Rgraphviz/versions/2.16.0/topics/GraphvizLayouts for more details on these layout algorithms.
Usage
Direct Invocation
{{#invoke:DependencyGraph|main}}
Module DOT Output
Non-clustered
Lua error: Module:DependencyGraph:76: "Module:Enemies/data/pre" does not exist table#1 {
["Module:Ability"] = table#2 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, }, ["Module:Ability/Conclave/data"] = table#3 { }, ["Module:Ability/data"] = table#4 { }, ["Module:Ability/data/stats"] = table#5 { }, ["Module:Ability/infobox"] = table#6 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, ["Module:Tooltips"] = 0, ["Module:Version"] = 0, }, ["Module:Ability/infoboxTEST"] = table#7 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, ["Module:Tooltips"] = 0, ["Module:Version"] = 0, }, ["Module:Acquisition"] = table#8 { ["Module:Blueprints/data"] = 0, ["Module:DropTables/data"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Acquisition/data"] = table#9 { }, ["Module:Acquisition/dev"] = table#10 { ["Dev:Entrypoint"] = 0, ["Dev:User error"] = 0, ["Module:Acquisition/data"] = 0, ["Module:Icon"] = 0, ["Module:Lua"] = 0, ["Module:Math"] = 0, ["Module:String"] = 0, }, ["Module:Acquisition/testcases"] = table#11 { ["Dev:User error"] = 0, }, ["Module:Arcane"] = table#12 { ["Module:Arcane/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Arcane/data"] = table#13 { }, ["Module:Arcane/dev"] = table#14 { }, ["Module:Arcane/infobox"] = table#15 { ["Module:Arcane/data"] = 0, ["Module:DropTables"] = 0, ["Module:DropTables/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Vendors"] = 0, }, ["Module:Arguments"] = table#16 { ["Module:Arguments"] = 0, ["Module:I18n"] = 0, }, ["Module:Arguments/i18n"] = table#17 { }, ["Module:Autapomorphy DevSandbox"] = table#18 { ["Module:Icon"] = 0, ["Module:Modular/data"] = 0, ["Module:Shared"] = 0, ["Module:Version"] = 0, ["Module:Weapons/Conclave/data"] = 0, ["Module:Weapons/data"] = 0, }, ["Module:Avionics"] = table#19 { ["Module:Avionics/data"] = 0, ["Module:Icon"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Version"] = 0, }, ["Module:Avionics/data"] = table#20 { ["Module:Avionics/data/desc"] = 0, ["Module:Icon"] = 0, ["Module:Version"] = 0, }, ["Module:Avionics/data/desc"] = table#21 { }, ["Module:Baro"] = table#22 { ["Module:Arguments"] = 0, ["Module:Baro/data"] = 0, ["Module:Date"] = 0, ["Module:Entrypoint"] = 0, ["Module:Math"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Baro/data"] = table#23 { }, ["Module:Baro/data/dev"] = table#24 { }, ["Module:Baro/data/visits"] = table#25 { ["Module:Baro/data"] = 0, }, ["Module:Baro/history"] = table#26 { ["Module:Baro/data"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Baro/testcases"] = table#27 { }, ["Module:Blueprints/data"] = table#28 { }, ["Module:Blueprints/data/dev"] = table#29 { }, ["Module:BuildRequire"] = table#30 { ["Module:Icon"] = 0, }, ["Module:CSV"] = table#31 { ["Module:CSV"] = 0, }, ["Module:ChickenArchive"] = table#32 { ["Module:ChickenTest/data"] = 0, ["Module:Icon/data"] = 0, }, ["Module:ChickenTest"] = table#33 { ["Module:Icon/data"] = 0, }, ["Module:ChickenTest/data"] = table#34 { }, ["Module:ChickenTest2"] = table#35 { ["Module:ChickenTest/data"] = 0, }, ["Module:Codec"] = table#36 { }, ["Module:Codex"] = table#37 { ["Module:Codex/data"] = 0, ["Module:Table"] = 0, }, ["Module:Codex/data"] = table#38 { }, ["Module:Common"] = table#39 { ["Module:Entrypoint"] = 0, }, ["Module:Common/i18n"] = table#40 { }, ["Module:Companions/data"] = table#41 { }, ["Module:Companions/infobox"] = table#42 { ["Module:Baro"] = 0, ["Module:Companions/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Math"] = 0, ["Module:Polarity"] = 0, ["Module:Tooltips"] = 0, ["Module:Vendors"] = 0, ["Module:Version"] = 0, }, ["Module:Conservation"] = table#43 { ["Module:Conservation/data"] = 0, ["Module:Table"] = 0, }, ["Module:Conservation/data"] = table#44 { }, ["Module:Conservation/infobox"] = table#45 { ["Module:Conservation/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Version"] = 0, }, ["Module:Conservation/testcases"] = table#46 { }, ["Module:Cosmetics/data"] = table#47 { }, ["Module:Cost"] = table#48 { ["Module:Blueprints/data"] = 0, ["Module:Icon"] = 0, ["Module:Math"] = 0, ["Module:Research/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:CroqueTest"] = table#49 { ["Module:CroqueTest/BKT"] = 0, ["Module:CroqueTest/data"] = 0, ["Module:CroqueTest/keywords"] = 0, ["Module:Research/data"] = 0, ["Module:Warframes/data"] = 0, ["Module:Weapons/data"] = 0, }, ["Module:CroqueTest/BKT"] = table#50 { }, ["Module:CroqueTest/data"] = table#51 { }, ["Module:CroqueTest/keywords"] = table#52 { }, ["Module:CroqueTest2"] = table#53 { ["Module:Shared"] = 0, ["Module:Version"] = 0, }, ["Module:CroqueTest2/DV10"] = table#54 { }, ["Module:CroqueTest2/DV11"] = table#55 { }, ["Module:CroqueTest2/DV12"] = table#56 { }, ["Module:CroqueTest2/DV13"] = table#57 { }, ["Module:CroqueTest2/DV14"] = table#58 { }, ["Module:CroqueTest2/DV15"] = table#59 { }, ["Module:CroqueTest2/DV17"] = table#60 { }, ["Module:CroqueTest2/DV18"] = table#61 { }, ["Module:CroqueTest2/DV20"] = table#62 { }, ["Module:CroqueTest2/DV21"] = table#63 { }, ["Module:CroqueTest2/DV22"] = table#64 { }, ["Module:CroqueTest2/DV6"] = table#65 { }, ["Module:CroqueTest2/DV7"] = table#66 { }, ["Module:CroqueTest2/DV8"] = table#67 { }, ["Module:CroqueTest2/DV9"] = table#68 { }, ["Module:CroqueTest2/data"] = table#69 { }, ["Module:DamageTypes"] = table#70 { ["Module:DamageTypes/data"] = 0, ["Module:Icon/data"] = 0, ["Module:Tooltips"] = 0, }, ["Module:DamageTypes/data"] = table#71 { }, ["Module:DamageTypes/testcases"] = table#72 { }, ["Module:Database"] = table#73 { }, ["Module:DatastoreManifest"] = table#74 { }, ["Module:Date"] = table#75 { }, ["Module:Decorations"] = table#76 { ["Module:Decorations/data"] = 0, ["Module:Math"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Decrees/data"] = table#77 { }, ["Module:Delay"] = table#78 { }, ["Module:Docbunto"] = table#79 { ["Module:Docbunto/references"] = 0, ["Module:I18n"] = 0, ["Module:Lexer"] = 0, ["Module:Unindent"] = 0, ["Module:Yesno"] = 0, }, ["Module:Docbunto/cli"] = table#80 { ["Dev:CLI"] = 0, ["Dev:Docbunto"] = 0, ["Dev:FrameTools"] = 0, ["Dev:Json"] = 0, }, ["Module:Docbunto/i18n"] = table#81 { }, ["Module:Docbunto/references"] = table#82 { }, ["Module:Docbunto/testcases"] = table#83 { ["Dev:Unindent"] = 0, }, ["Module:DojoRoom/data"] = table#84 { }, ["Module:DropTables"] = table#85 { ["Module:Delay"] = 0, ["Module:DropTables/data"] = 0, ["Module:Icon"] = 0, ["Module:Missions/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Void"] = 0, ["Module:Void/data"] = 0, }, ["Module:DropTables/JSON"] = table#86 { ["Module:DropTables/JSON/"] = 0, }, ["Module:DropTables/JSON/Cetus Bounties"] = table#87 { }, ["Module:DropTables/JSON/Fortuna Bounties"] = table#88 { }, ["Module:DropTables/JSON/Necralisk Bounties"] = table#89 { }, ["Module:DropTables/JSON/Sorties"] = table#90 { }, ["Module:DropTables/JSON/Transient"] = table#91 { }, ["Module:DropTables/dev"] = table#92 { ["Module:DropTables/data"] = 0, ["Module:Icon"] = 0, ["Module:Math"] = 0, ["Module:Missions/data"] = 0, ["Module:Mods/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Void"] = 0, ["Module:Void/data"] = 0, }, ["Module:Enemies/data"] = table#93 { ["Module:Enemies/data"] = 0, ["Module:LuaSerializer"] = 0, }, ["Module:Enemies/data/corpus"] = table#94 { }, ["Module:Enemies/data/grineer"] = table#95 { }, ["Module:Enemies/data/infestation"] = table#96 { }, ["Module:Enemies/data/narmer"] = table#97 { }, ["Module:Enemies/data/orokin"] = table#98 { }, ["Module:Enemies/data/pre"] = table#99 { }, ["Module:Enemies/data/sentient"] = table#100 { }, ["Module:Enemies/data/stalker"] = table#101 { }, ["Module:Enemies/data/themurmur"] = table#102 { }, ["Module:Enemies/data/unaffiliated"] = table#103 { }, ["Module:Enemies/infobox"] = table#104 { }, ["Module:Entrypoint"] = table#105 { }, ["Module:Enum/data"] = table#106 { }, ["Module:FINNER DropTables Test"] = table#107 { }, ["Module:FINNER Icon Test"] = table#108 { }, ["Module:FINNER Test"] = table#109 { }, ["Module:FINNER Test/data"] = table#110 { }, ["Module:FINNER Test/data/1"] = table#111 { }, ["Module:FINNER Test/data/2"] = table#112 { }, ["Module:FINNER Test/data/3"] = table#113 { }, ["Module:FINNER Test/data/4"] = table#114 { }, ["Module:FINNER Test/data/5"] = table#115 { }, ["Module:FINNER Test/data/6"] = table#116 { }, ["Module:FINNER Test/data/7"] = table#117 { }, ["Module:FINNER Test/data/8"] = table#118 { }, ["Module:FINNER Warframe Test"] = table#119 { }, ["Module:FINNER Weapon Test"] = table#120 { }, ["Module:FactionScript"] = table#121 { }, ["Module:FactionScript/data"] = table#122 { }, ["Module:Factions/data"] = table#123 { }, ["Module:FallbackList"] = table#124 { }, ["Module:FalterTest"] = table#125 { }, ["Module:FalterTest/data"] = table#126 { }, ["Module:Flaicher"] = table#127 { }, ["Module:Flaicher/Conv"] = table#128 { }, ["Module:Flaicher/Conv/data"] = table#129 { }, ["Module:Flaicher/DropTables"] = table#130 { }, ["Module:Flaicher/DropTables/data"] = table#131 { }, ["Module:Flaicher/Mods"] = table#132 { }, ["Module:Flaicher/dispoData"] = table#133 { }, ["Module:FlaicherTest"] = table#134 { }, ["Module:Focus"] = table#135 { }, ["Module:Focus/data"] = table#136 { }, ["Module:Focus/data/archived"] = table#137 { }, ["Module:Focus/infobox"] = table#138 { }, ["Module:FormatingTool"] = table#139 { }, ["Module:FormatingTool/data"] = table#140 { }, ["Module:FormatingTool/data2"] = table#141 { }, ["Module:FormatingTool/missions"] = table#142 { }, ["Module:Gallery"] = table#143 { }, ["Module:Gallery/testcases"] = table#144 { }, ["Module:GigaTest"] = table#145 { }, ["Module:GuaranteedRewards/data"] = table#146 { }, ["Module:HexTest"] = table#147 { }, ["Module:HexTest/data"] = table#148 { }, ["Module:I18n"] = table#149 { }, ["Module:I18n/testcases"] = table#150 { }, ["Module:Icon"] = table#151 { }, ["Module:Icon/data"] = table#152 { }, ["Module:Icon/testcases"] = table#153 { }, ["Module:Infobox"] = table#154 { }, ["Module:Infobox/i18n"] = table#155 { }, ["Module:InfoboxBuilder"] = table#156 { }, ["Module:InfoboxBuilder/dev"] = table#157 { }, ["Module:Inspect"] = table#158 { }, ["Module:InternalNames"] = table#159 { }, ["Module:JSON"] = table#160 { }, ["Module:KeyBindings"] = table#161 { }, ["Module:KeyBindings/data"] = table#162 { }, ["Module:Keys/data"] = table#163 { }, ["Module:LanguageList"] = table#164 { }, ["Module:Lexer"] = table#165 { }, ["Module:Lua"] = table#166 { }, ["Module:LuaClassSystem"] = table#167 { }, ["Module:LuaSerializer"] = table#168 { }, ["Module:LuaSerializer/dev"] = table#169 { }, ["Module:Map"] = table#170 { }, ["Module:Map/testcases"] = table#171 { }, ["Module:MasteryRank"] = table#172 { }, ["Module:MasteryRank/dev"] = table#173 { }, ["Module:Math"] = table#174 { }, ["Module:Math/dev"] = table#175 { }, ["Module:Math/i18n"] = table#176 { }, ["Module:Math/testcases"] = table#177 { }, ["Module:Math/testcases/module"] = table#178 { }, ["Module:Maximization"] = table#179 { }, ["Module:Maximization/data"] = table#180 { }, ["Module:Mbox"] = table#181 { }, ["Module:Mbox/i18n"] = table#182 { }, ["Module:Missions"] = table#183 { }, ["Module:Missions/data"] = table#184 { }, ["Module:Missions/data/dev"] = table#185 { }, ["Module:Missions/dev"] = table#186 { }, ["Module:Missions/infobox"] = table#187 { }, ["Module:Missions/page"] = table#188 { }, ["Module:Mods"] = table#189 { }, ["Module:Mods/csv"] = table#190 { }, ["Module:Mods/csv2"] = table#191 { }, ["Module:Mods/data/validate"] = table#192 { }, ["Module:Mods/infobox"] = table#193 { }, ["Module:Mods/testcases"] = table#194 { }, ["Module:Modular"] = table#195 { }, ["Module:Modular/data"] = table#196 { }, ["Module:ModuleTest"] = table#197 { }, ["Module:Music/data"] = table#198 { }, ["Module:Navbox"] = table#199 { }, ["Module:Navigation"] = table#200 { }, ["Module:Navigation/dev"] = table#201 { }, ["Module:NightwaveActs"] = table#202 { }, ["Module:NightwaveActs/acts.json"] = table#203 { }, ["Module:NightwaveActs/dev"] = table#204 { }, ["Module:Placeholder"] = table#205 { }, ["Module:Polarity"] = table#206 { }, ["Module:Reference"] = table#207 { }, ["Module:ReleaseStatus"] = table#208 { }, ["Module:ReleaseStatus/data"] = table#209 { }, ["Module:ReleaseStatus/i18n"] = table#210 { }, ["Module:RemoveCategory"] = table#211 { }, ["Module:Research/data"] = table#212 { }, ["Module:Resources"] = table#213 { }, ["Module:Resources/data"] = table#214 { }, ["Module:Resources/data/dev"] = table#215 { }, ["Module:Resources/data/validate"] = table#216 { }, ["Module:Resources/infobox"] = table#217 { }, ["Module:Sandbox"] = table#218 { }, ["Module:Sandbox/DutyS12345"] = table#219 { }, ["Module:Sandbox/Hilycker/SortTest"] = table#220 { }, ["Module:Sandbox/Hilycker/SortTest/data"] = table#221 { }, ["Module:Sandbox/Moxian"] = table#222 { }, ["Module:Sandbox/SkipThisAd/DropTables"] = table#223 { }, ["Module:Sandbox/lonnstyle/Warframes/infobox"] = table#224 { }, ["Module:ScientiaStances"] = table#225 { }, ["Module:ScientiaStances/data"] = table#226 { }, ["Module:ScientiaStances/sharedCombosData"] = table#227 { }, ["Module:ScientiaTest"] = table#228 { }, ["Module:ScientiaTest/data"] = table#229 { }, ["Module:ScientiaTest/i18n"] = table#230 { }, ["Module:Shared"] = table#231 { }, ["Module:Shared/testcases"] = table#232 { }, ["Module:Sigils/data"] = table#233 { }, ["Module:SnekwTest"] = table#234 { }, ["Module:Stances"] = table#235 { }, ["Module:Stances/data"] = table#236 { }, ["Module:Stances/data/dev"] = table#237 { }, ["Module:Stances/dev"] = table#238 { }, ["Module:StatObject"] = table#239 { }, ["Module:String"] = table#240 { }, ["Module:String/testcases"] = table#241 { }, ["Module:Switch Infobox"] = table#242 { }, ["Module:Syndicates/data"] = table#243 { }, ["Module:SynthTest"] = table#244 { }, ["Module:Table"] = table#245 { }, ["Module:Table/testcases"] = table#246 { }, ["Module:TennoGen"] = table#247 { }, ["Module:TennoGen/data"] = table#248 { }, ["Module:TennoScript"] = table#249 { }, ["Module:TestHarness"] = table#250 { }, ["Module:TestHarness/i18n"] = table#251 { }, ["Module:TextIcons"] = table#252 { }, ["Module:TextIcons/data"] = table#253 { }, ["Module:Tooltips"] = table#254 { }, ["Module:Tooltips/data"] = table#255 { }, ["Module:Tooltips/data/Ability"] = table#256 { }, ["Module:Tooltips/data/Arcane"] = table#257 { }, ["Module:Tooltips/data/DamageTypes"] = table#258 { }, ["Module:Tooltips/data/Mods"] = table#259 { }, ["Module:Tooltips/data/Void"] = table#260 { }, ["Module:Tooltips/data/Warframes"] = table#261 { }, ["Module:Tooltips/data/Weapons"] = table#262 { }, ["Module:Tooltips/dev"] = table#263 { }, ["Module:Tooltips/icon"] = table#264 { }, ["Module:Tooltips/icon/dev"] = table#265 { }, ["Module:Tooltips/testcases"] = table#266 { }, ["Module:Tooltips/tip"] = table#267 { }, ["Module:Tooltips/tip/dev"] = table#268 { }, ["Module:TrajosAcquisition"] = table#269 { }, ["Module:TrajosVoid"] = table#270 { }, ["Module:TranslationExamples"] = table#271 { }, ["Module:Unindent"] = table#272 { }, ["Module:Upgrades/data"] = table#273 { }, ["Module:UserError"] = table#274 { }, ["Module:Vendors"] = table#275 { }, ["Module:Vendors/data"] = table#276 { }, ["Module:Version"] = table#277 { }, ["Module:Void"] = table#278 { }, ["Module:Void/data"] = table#279 { }, ["Module:Void/data/dev"] = table#280 { }, ["Module:Void/data/validate"] = table#281 { }, ["Module:Void/dev"] = table#282 { }, ["Module:Void/page"] = table#283 { }, ["Module:VoidByReward"] = table#284 { }, ["Module:WDSButton"] = table#285 { }, ["Module:WDSButton/data"] = table#286 { }, ["Module:Warframes"] = table#287 { }, ["Module:Warframes/Conclave/data"] = table#288 { }, ["Module:Warframes/data"] = table#289 { }, ["Module:Warframes/infobox"] = table#290 { }, ["Module:Warframes/testcases"] = table#291 { }, ["Module:Weapons"] = table#292 { }, ["Module:Weapons/Conclave/data"] = table#293 { }, ["Module:Weapons/Conclave/data/melee"] = table#294 { }, ["Module:Weapons/Conclave/data/primary"] = table#295 { }, ["Module:Weapons/Conclave/data/secondary"] = table#296 { }, ["Module:Weapons/characteristics"] = table#297 { }, ["Module:Weapons/compare"] = table#298 { }, ["Module:Weapons/comptable"] = table#299 { }, ["Module:Weapons/csv"] = table#300 { }, ["Module:Weapons/data"] = table#301 { }, ["Module:Weapons/data/archwing"] = table#302 { }, ["Module:Weapons/data/companion"] = table#303 { }, ["Module:Weapons/data/credits"] = table#304 { }, ["Module:Weapons/data/melee"] = table#305 { }, ["Module:Weapons/data/misc"] = table#306 { }, ["Module:Weapons/data/modular"] = table#307 { }, ["Module:Weapons/data/primary"] = table#308 { }, ["Module:Weapons/data/railjack"] = table#309 { }, ["Module:Weapons/data/secondary"] = table#310 { }, ["Module:Weapons/data/validate"] = table#311 { }, ["Module:Weapons/dev"] = table#312 { }, ["Module:Weapons/infobox"] = table#313 { }, ["Module:Weapons/nav"] = table#314 { }, ["Module:Weapons/ppdata"] = table#315 { }, ["Module:Weapons/ppdata/seeder"] = table#316 { }, ["Module:Weapons/preprocess"] = table#317 { }, ["Module:Weapons/testcases"] = table#318 { }, ["Module:WorldState"] = table#319 { }, ["Module:Worldstate/data"] = table#320 { }, ["Module:Yesno"] = table#321 { }, ["Module:Yesno/testcases"] = table#322 { },
}.
Clustered
Lua error: Module:DependencyGraph:76: "Module:Enemies/data/pre" does not exist table#1 {
["Module:Ability"] = table#2 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, }, ["Module:Ability/Conclave/data"] = table#3 { }, ["Module:Ability/data"] = table#4 { }, ["Module:Ability/data/stats"] = table#5 { }, ["Module:Ability/infobox"] = table#6 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, ["Module:Tooltips"] = 0, ["Module:Version"] = 0, }, ["Module:Ability/infoboxTEST"] = table#7 { ["Module:Ability/Conclave/data"] = 0, ["Module:Ability/data"] = 0, ["Module:Tooltips"] = 0, ["Module:Version"] = 0, }, ["Module:Acquisition"] = table#8 { ["Module:Blueprints/data"] = 0, ["Module:DropTables/data"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Acquisition/data"] = table#9 { }, ["Module:Acquisition/dev"] = table#10 { ["Dev:Entrypoint"] = 0, ["Dev:User error"] = 0, ["Module:Acquisition/data"] = 0, ["Module:Icon"] = 0, ["Module:Lua"] = 0, ["Module:Math"] = 0, ["Module:String"] = 0, }, ["Module:Acquisition/testcases"] = table#11 { ["Dev:User error"] = 0, }, ["Module:Arcane"] = table#12 { ["Module:Arcane/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Arcane/data"] = table#13 { }, ["Module:Arcane/dev"] = table#14 { }, ["Module:Arcane/infobox"] = table#15 { ["Module:Arcane/data"] = 0, ["Module:DropTables"] = 0, ["Module:DropTables/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Vendors"] = 0, }, ["Module:Arguments"] = table#16 { ["Module:Arguments"] = 0, ["Module:I18n"] = 0, }, ["Module:Arguments/i18n"] = table#17 { }, ["Module:Autapomorphy DevSandbox"] = table#18 { ["Module:Icon"] = 0, ["Module:Modular/data"] = 0, ["Module:Shared"] = 0, ["Module:Version"] = 0, ["Module:Weapons/Conclave/data"] = 0, ["Module:Weapons/data"] = 0, }, ["Module:Avionics"] = table#19 { ["Module:Avionics/data"] = 0, ["Module:Icon"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Version"] = 0, }, ["Module:Avionics/data"] = table#20 { ["Module:Avionics/data/desc"] = 0, ["Module:Icon"] = 0, ["Module:Version"] = 0, }, ["Module:Avionics/data/desc"] = table#21 { }, ["Module:Baro"] = table#22 { ["Module:Arguments"] = 0, ["Module:Baro/data"] = 0, ["Module:Date"] = 0, ["Module:Entrypoint"] = 0, ["Module:Math"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Baro/data"] = table#23 { }, ["Module:Baro/data/dev"] = table#24 { }, ["Module:Baro/data/visits"] = table#25 { ["Module:Baro/data"] = 0, }, ["Module:Baro/history"] = table#26 { ["Module:Baro/data"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Baro/testcases"] = table#27 { }, ["Module:Blueprints/data"] = table#28 { }, ["Module:Blueprints/data/dev"] = table#29 { }, ["Module:BuildRequire"] = table#30 { ["Module:Icon"] = 0, }, ["Module:CSV"] = table#31 { ["Module:CSV"] = 0, }, ["Module:ChickenArchive"] = table#32 { ["Module:ChickenTest/data"] = 0, ["Module:Icon/data"] = 0, }, ["Module:ChickenTest"] = table#33 { ["Module:Icon/data"] = 0, }, ["Module:ChickenTest/data"] = table#34 { }, ["Module:ChickenTest2"] = table#35 { ["Module:ChickenTest/data"] = 0, }, ["Module:Codec"] = table#36 { }, ["Module:Codex"] = table#37 { ["Module:Codex/data"] = 0, ["Module:Table"] = 0, }, ["Module:Codex/data"] = table#38 { }, ["Module:Common"] = table#39 { ["Module:Entrypoint"] = 0, }, ["Module:Common/i18n"] = table#40 { }, ["Module:Companions/data"] = table#41 { }, ["Module:Companions/infobox"] = table#42 { ["Module:Baro"] = 0, ["Module:Companions/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Math"] = 0, ["Module:Polarity"] = 0, ["Module:Tooltips"] = 0, ["Module:Vendors"] = 0, ["Module:Version"] = 0, }, ["Module:Conservation"] = table#43 { ["Module:Conservation/data"] = 0, ["Module:Table"] = 0, }, ["Module:Conservation/data"] = table#44 { }, ["Module:Conservation/infobox"] = table#45 { ["Module:Conservation/data"] = 0, ["Module:InfoboxBuilder"] = 0, ["Module:Version"] = 0, }, ["Module:Conservation/testcases"] = table#46 { }, ["Module:Cosmetics/data"] = table#47 { }, ["Module:Cost"] = table#48 { ["Module:Blueprints/data"] = 0, ["Module:Icon"] = 0, ["Module:Math"] = 0, ["Module:Research/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:CroqueTest"] = table#49 { ["Module:CroqueTest/BKT"] = 0, ["Module:CroqueTest/data"] = 0, ["Module:CroqueTest/keywords"] = 0, ["Module:Research/data"] = 0, ["Module:Warframes/data"] = 0, ["Module:Weapons/data"] = 0, }, ["Module:CroqueTest/BKT"] = table#50 { }, ["Module:CroqueTest/data"] = table#51 { }, ["Module:CroqueTest/keywords"] = table#52 { }, ["Module:CroqueTest2"] = table#53 { ["Module:Shared"] = 0, ["Module:Version"] = 0, }, ["Module:CroqueTest2/DV10"] = table#54 { }, ["Module:CroqueTest2/DV11"] = table#55 { }, ["Module:CroqueTest2/DV12"] = table#56 { }, ["Module:CroqueTest2/DV13"] = table#57 { }, ["Module:CroqueTest2/DV14"] = table#58 { }, ["Module:CroqueTest2/DV15"] = table#59 { }, ["Module:CroqueTest2/DV17"] = table#60 { }, ["Module:CroqueTest2/DV18"] = table#61 { }, ["Module:CroqueTest2/DV20"] = table#62 { }, ["Module:CroqueTest2/DV21"] = table#63 { }, ["Module:CroqueTest2/DV22"] = table#64 { }, ["Module:CroqueTest2/DV6"] = table#65 { }, ["Module:CroqueTest2/DV7"] = table#66 { }, ["Module:CroqueTest2/DV8"] = table#67 { }, ["Module:CroqueTest2/DV9"] = table#68 { }, ["Module:CroqueTest2/data"] = table#69 { }, ["Module:DamageTypes"] = table#70 { ["Module:DamageTypes/data"] = 0, ["Module:Icon/data"] = 0, ["Module:Tooltips"] = 0, }, ["Module:DamageTypes/data"] = table#71 { }, ["Module:DamageTypes/testcases"] = table#72 { }, ["Module:Database"] = table#73 { }, ["Module:DatastoreManifest"] = table#74 { }, ["Module:Date"] = table#75 { }, ["Module:Decorations"] = table#76 { ["Module:Decorations/data"] = 0, ["Module:Math"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, }, ["Module:Decrees/data"] = table#77 { }, ["Module:Delay"] = table#78 { }, ["Module:Docbunto"] = table#79 { ["Module:Docbunto/references"] = 0, ["Module:I18n"] = 0, ["Module:Lexer"] = 0, ["Module:Unindent"] = 0, ["Module:Yesno"] = 0, }, ["Module:Docbunto/cli"] = table#80 { ["Dev:CLI"] = 0, ["Dev:Docbunto"] = 0, ["Dev:FrameTools"] = 0, ["Dev:Json"] = 0, }, ["Module:Docbunto/i18n"] = table#81 { }, ["Module:Docbunto/references"] = table#82 { }, ["Module:Docbunto/testcases"] = table#83 { ["Dev:Unindent"] = 0, }, ["Module:DojoRoom/data"] = table#84 { }, ["Module:DropTables"] = table#85 { ["Module:Delay"] = 0, ["Module:DropTables/data"] = 0, ["Module:Icon"] = 0, ["Module:Missions/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Void"] = 0, ["Module:Void/data"] = 0, }, ["Module:DropTables/JSON"] = table#86 { ["Module:DropTables/JSON/"] = 0, }, ["Module:DropTables/JSON/Cetus Bounties"] = table#87 { }, ["Module:DropTables/JSON/Fortuna Bounties"] = table#88 { }, ["Module:DropTables/JSON/Necralisk Bounties"] = table#89 { }, ["Module:DropTables/JSON/Sorties"] = table#90 { }, ["Module:DropTables/JSON/Transient"] = table#91 { }, ["Module:DropTables/dev"] = table#92 { ["Module:DropTables/data"] = 0, ["Module:Icon"] = 0, ["Module:Math"] = 0, ["Module:Missions/data"] = 0, ["Module:Mods/data"] = 0, ["Module:String"] = 0, ["Module:Table"] = 0, ["Module:Tooltips"] = 0, ["Module:Void"] = 0, ["Module:Void/data"] = 0, }, ["Module:Enemies/data"] = table#93 { ["Module:Enemies/data"] = 0, ["Module:LuaSerializer"] = 0, }, ["Module:Enemies/data/corpus"] = table#94 { }, ["Module:Enemies/data/grineer"] = table#95 { }, ["Module:Enemies/data/infestation"] = table#96 { }, ["Module:Enemies/data/narmer"] = table#97 { }, ["Module:Enemies/data/orokin"] = table#98 { }, ["Module:Enemies/data/pre"] = table#99 { }, ["Module:Enemies/data/sentient"] = table#100 { }, ["Module:Enemies/data/stalker"] = table#101 { }, ["Module:Enemies/data/themurmur"] = table#102 { }, ["Module:Enemies/data/unaffiliated"] = table#103 { }, ["Module:Enemies/infobox"] = table#104 { }, ["Module:Entrypoint"] = table#105 { }, ["Module:Enum/data"] = table#106 { }, ["Module:FINNER DropTables Test"] = table#107 { }, ["Module:FINNER Icon Test"] = table#108 { }, ["Module:FINNER Test"] = table#109 { }, ["Module:FINNER Test/data"] = table#110 { }, ["Module:FINNER Test/data/1"] = table#111 { }, ["Module:FINNER Test/data/2"] = table#112 { }, ["Module:FINNER Test/data/3"] = table#113 { }, ["Module:FINNER Test/data/4"] = table#114 { }, ["Module:FINNER Test/data/5"] = table#115 { }, ["Module:FINNER Test/data/6"] = table#116 { }, ["Module:FINNER Test/data/7"] = table#117 { }, ["Module:FINNER Test/data/8"] = table#118 { }, ["Module:FINNER Warframe Test"] = table#119 { }, ["Module:FINNER Weapon Test"] = table#120 { }, ["Module:FactionScript"] = table#121 { }, ["Module:FactionScript/data"] = table#122 { }, ["Module:Factions/data"] = table#123 { }, ["Module:FallbackList"] = table#124 { }, ["Module:FalterTest"] = table#125 { }, ["Module:FalterTest/data"] = table#126 { }, ["Module:Flaicher"] = table#127 { }, ["Module:Flaicher/Conv"] = table#128 { }, ["Module:Flaicher/Conv/data"] = table#129 { }, ["Module:Flaicher/DropTables"] = table#130 { }, ["Module:Flaicher/DropTables/data"] = table#131 { }, ["Module:Flaicher/Mods"] = table#132 { }, ["Module:Flaicher/dispoData"] = table#133 { }, ["Module:FlaicherTest"] = table#134 { }, ["Module:Focus"] = table#135 { }, ["Module:Focus/data"] = table#136 { }, ["Module:Focus/data/archived"] = table#137 { }, ["Module:Focus/infobox"] = table#138 { }, ["Module:FormatingTool"] = table#139 { }, ["Module:FormatingTool/data"] = table#140 { }, ["Module:FormatingTool/data2"] = table#141 { }, ["Module:FormatingTool/missions"] = table#142 { }, ["Module:Gallery"] = table#143 { }, ["Module:Gallery/testcases"] = table#144 { }, ["Module:GigaTest"] = table#145 { }, ["Module:GuaranteedRewards/data"] = table#146 { }, ["Module:HexTest"] = table#147 { }, ["Module:HexTest/data"] = table#148 { }, ["Module:I18n"] = table#149 { }, ["Module:I18n/testcases"] = table#150 { }, ["Module:Icon"] = table#151 { }, ["Module:Icon/data"] = table#152 { }, ["Module:Icon/testcases"] = table#153 { }, ["Module:Infobox"] = table#154 { }, ["Module:Infobox/i18n"] = table#155 { }, ["Module:InfoboxBuilder"] = table#156 { }, ["Module:InfoboxBuilder/dev"] = table#157 { }, ["Module:Inspect"] = table#158 { }, ["Module:InternalNames"] = table#159 { }, ["Module:JSON"] = table#160 { }, ["Module:KeyBindings"] = table#161 { }, ["Module:KeyBindings/data"] = table#162 { }, ["Module:Keys/data"] = table#163 { }, ["Module:LanguageList"] = table#164 { }, ["Module:Lexer"] = table#165 { }, ["Module:Lua"] = table#166 { }, ["Module:LuaClassSystem"] = table#167 { }, ["Module:LuaSerializer"] = table#168 { }, ["Module:LuaSerializer/dev"] = table#169 { }, ["Module:Map"] = table#170 { }, ["Module:Map/testcases"] = table#171 { }, ["Module:MasteryRank"] = table#172 { }, ["Module:MasteryRank/dev"] = table#173 { }, ["Module:Math"] = table#174 { }, ["Module:Math/dev"] = table#175 { }, ["Module:Math/i18n"] = table#176 { }, ["Module:Math/testcases"] = table#177 { }, ["Module:Math/testcases/module"] = table#178 { }, ["Module:Maximization"] = table#179 { }, ["Module:Maximization/data"] = table#180 { }, ["Module:Mbox"] = table#181 { }, ["Module:Mbox/i18n"] = table#182 { }, ["Module:Missions"] = table#183 { }, ["Module:Missions/data"] = table#184 { }, ["Module:Missions/data/dev"] = table#185 { }, ["Module:Missions/dev"] = table#186 { }, ["Module:Missions/infobox"] = table#187 { }, ["Module:Missions/page"] = table#188 { }, ["Module:Mods"] = table#189 { }, ["Module:Mods/csv"] = table#190 { }, ["Module:Mods/csv2"] = table#191 { }, ["Module:Mods/data/validate"] = table#192 { }, ["Module:Mods/infobox"] = table#193 { }, ["Module:Mods/testcases"] = table#194 { }, ["Module:Modular"] = table#195 { }, ["Module:Modular/data"] = table#196 { }, ["Module:ModuleTest"] = table#197 { }, ["Module:Music/data"] = table#198 { }, ["Module:Navbox"] = table#199 { }, ["Module:Navigation"] = table#200 { }, ["Module:Navigation/dev"] = table#201 { }, ["Module:NightwaveActs"] = table#202 { }, ["Module:NightwaveActs/acts.json"] = table#203 { }, ["Module:NightwaveActs/dev"] = table#204 { }, ["Module:Placeholder"] = table#205 { }, ["Module:Polarity"] = table#206 { }, ["Module:Reference"] = table#207 { }, ["Module:ReleaseStatus"] = table#208 { }, ["Module:ReleaseStatus/data"] = table#209 { }, ["Module:ReleaseStatus/i18n"] = table#210 { }, ["Module:RemoveCategory"] = table#211 { }, ["Module:Research/data"] = table#212 { }, ["Module:Resources"] = table#213 { }, ["Module:Resources/data"] = table#214 { }, ["Module:Resources/data/dev"] = table#215 { }, ["Module:Resources/data/validate"] = table#216 { }, ["Module:Resources/infobox"] = table#217 { }, ["Module:Sandbox"] = table#218 { }, ["Module:Sandbox/DutyS12345"] = table#219 { }, ["Module:Sandbox/Hilycker/SortTest"] = table#220 { }, ["Module:Sandbox/Hilycker/SortTest/data"] = table#221 { }, ["Module:Sandbox/Moxian"] = table#222 { }, ["Module:Sandbox/SkipThisAd/DropTables"] = table#223 { }, ["Module:Sandbox/lonnstyle/Warframes/infobox"] = table#224 { }, ["Module:ScientiaStances"] = table#225 { }, ["Module:ScientiaStances/data"] = table#226 { }, ["Module:ScientiaStances/sharedCombosData"] = table#227 { }, ["Module:ScientiaTest"] = table#228 { }, ["Module:ScientiaTest/data"] = table#229 { }, ["Module:ScientiaTest/i18n"] = table#230 { }, ["Module:Shared"] = table#231 { }, ["Module:Shared/testcases"] = table#232 { }, ["Module:Sigils/data"] = table#233 { }, ["Module:SnekwTest"] = table#234 { }, ["Module:Stances"] = table#235 { }, ["Module:Stances/data"] = table#236 { }, ["Module:Stances/data/dev"] = table#237 { }, ["Module:Stances/dev"] = table#238 { }, ["Module:StatObject"] = table#239 { }, ["Module:String"] = table#240 { }, ["Module:String/testcases"] = table#241 { }, ["Module:Switch Infobox"] = table#242 { }, ["Module:Syndicates/data"] = table#243 { }, ["Module:SynthTest"] = table#244 { }, ["Module:Table"] = table#245 { }, ["Module:Table/testcases"] = table#246 { }, ["Module:TennoGen"] = table#247 { }, ["Module:TennoGen/data"] = table#248 { }, ["Module:TennoScript"] = table#249 { }, ["Module:TestHarness"] = table#250 { }, ["Module:TestHarness/i18n"] = table#251 { }, ["Module:TextIcons"] = table#252 { }, ["Module:TextIcons/data"] = table#253 { }, ["Module:Tooltips"] = table#254 { }, ["Module:Tooltips/data"] = table#255 { }, ["Module:Tooltips/data/Ability"] = table#256 { }, ["Module:Tooltips/data/Arcane"] = table#257 { }, ["Module:Tooltips/data/DamageTypes"] = table#258 { }, ["Module:Tooltips/data/Mods"] = table#259 { }, ["Module:Tooltips/data/Void"] = table#260 { }, ["Module:Tooltips/data/Warframes"] = table#261 { }, ["Module:Tooltips/data/Weapons"] = table#262 { }, ["Module:Tooltips/dev"] = table#263 { }, ["Module:Tooltips/icon"] = table#264 { }, ["Module:Tooltips/icon/dev"] = table#265 { }, ["Module:Tooltips/testcases"] = table#266 { }, ["Module:Tooltips/tip"] = table#267 { }, ["Module:Tooltips/tip/dev"] = table#268 { }, ["Module:TrajosAcquisition"] = table#269 { }, ["Module:TrajosVoid"] = table#270 { }, ["Module:TranslationExamples"] = table#271 { }, ["Module:Unindent"] = table#272 { }, ["Module:Upgrades/data"] = table#273 { }, ["Module:UserError"] = table#274 { }, ["Module:Vendors"] = table#275 { }, ["Module:Vendors/data"] = table#276 { }, ["Module:Version"] = table#277 { }, ["Module:Void"] = table#278 { }, ["Module:Void/data"] = table#279 { }, ["Module:Void/data/dev"] = table#280 { }, ["Module:Void/data/validate"] = table#281 { }, ["Module:Void/dev"] = table#282 { }, ["Module:Void/page"] = table#283 { }, ["Module:VoidByReward"] = table#284 { }, ["Module:WDSButton"] = table#285 { }, ["Module:WDSButton/data"] = table#286 { }, ["Module:Warframes"] = table#287 { }, ["Module:Warframes/Conclave/data"] = table#288 { }, ["Module:Warframes/data"] = table#289 { }, ["Module:Warframes/infobox"] = table#290 { }, ["Module:Warframes/testcases"] = table#291 { }, ["Module:Weapons"] = table#292 { }, ["Module:Weapons/Conclave/data"] = table#293 { }, ["Module:Weapons/Conclave/data/melee"] = table#294 { }, ["Module:Weapons/Conclave/data/primary"] = table#295 { }, ["Module:Weapons/Conclave/data/secondary"] = table#296 { }, ["Module:Weapons/characteristics"] = table#297 { }, ["Module:Weapons/compare"] = table#298 { }, ["Module:Weapons/comptable"] = table#299 { }, ["Module:Weapons/csv"] = table#300 { }, ["Module:Weapons/data"] = table#301 { }, ["Module:Weapons/data/archwing"] = table#302 { }, ["Module:Weapons/data/companion"] = table#303 { }, ["Module:Weapons/data/credits"] = table#304 { }, ["Module:Weapons/data/melee"] = table#305 { }, ["Module:Weapons/data/misc"] = table#306 { }, ["Module:Weapons/data/modular"] = table#307 { }, ["Module:Weapons/data/primary"] = table#308 { }, ["Module:Weapons/data/railjack"] = table#309 { }, ["Module:Weapons/data/secondary"] = table#310 { }, ["Module:Weapons/data/validate"] = table#311 { }, ["Module:Weapons/dev"] = table#312 { }, ["Module:Weapons/infobox"] = table#313 { }, ["Module:Weapons/nav"] = table#314 { }, ["Module:Weapons/ppdata"] = table#315 { }, ["Module:Weapons/ppdata/seeder"] = table#316 { }, ["Module:Weapons/preprocess"] = table#317 { }, ["Module:Weapons/testcases"] = table#318 { }, ["Module:WorldState"] = table#319 { }, ["Module:Worldstate/data"] = table#320 { }, ["Module:Yesno"] = table#321 { }, ["Module:Yesno/testcases"] = table#322 { },
}.
Cleaning up non-clustered graph
If using dot
algorithm to render a non-clustered graph, then use the unflatten preprocessor to improve graph's aspect ratio:
unflatten -f -l5 -c13 fileName.dot
Wiki's Dependency Graphs
Dependency graphs of this wiki's codebase can be viewed on the Category:Dependency Graphs category.
Documentation
Package items
dependencygraph.enableClusters
(member; boolean)- Denotes whether or not clustering of nodes will occur
dependencygraph.main(frame)
(function)- Entry point of program.
- Parameter:
frame
Frame object (table) - Returns: Preformatted text of resultant DOT graph (string)
- Created with Docbunto
See Also
Code
--- '''DependencyGraph''' outputs a module dependency graph of this wiki's modules
-- using the [[wikipedia:DOT (graph description language)|DOT language]].<br />
--
-- Requires [[community:Help:DynamicPageList|Extension:DynamicPageList]] enabled on your wiki.
--
-- Recommended layout algorithms for rendering resultant DOT file:
-- * <code>fdp</code>/<code>sfdp</code> - useful for viewing entire codebase w/ clustering of module families
-- * <code>circo</code> - circular layout, useful for finding modules/submodules with the fewest dependencies
--
-- See https://www.rdocumentation.org/packages/Rgraphviz/versions/2.16.0/topics/GraphvizLayouts
-- for more details on these layout algorithms.
--
-- @module dependencygraph
-- @alias p
-- @author [[User:Cephalon Scientia|Cephalon Scientia]]
-- @image EN WARFRAME Wiki Dependency Graph.png
-- @require [[Module:Table]]
-- @release beta
-- <nowiki>
-- TODO: Module names inside documentation is being treated as dependencies even though
-- they may not be actual dependencies. Somehow get the strings within mw.loadData() and require()
-- functions instead to use as a module's actual dependencies. Note on limitations of Lua patterns.
-- @todo Explore way to output to GraphML format or convert DOT to GraphML to import into yED Graph Editor
local p = {}
-- TODO: If porting this module to the Dev wiki for global use, remove this import and directly implement
-- any used functions here
local Table = require('Module:Table')
local MODULE_LOCALIZATION = mw.site.namespaces[828].name
local MODULE_NAME_PATTERN = MODULE_LOCALIZATION..':[%a%d. /]+'
local DEV_MODULE_NAME_PATTERN = 'Dev:[%w /]+'
-- Capturing all possible characters that can be in a import function call,
-- includes possible characters in Module page name as well as Lua tokens
local POSSIBLE_CHAR_PATTERN = '[%w%[%]()\'" :/.=]+'
-- TODO: There are still false positives with require() and mw.loadData() statements that
-- are commented out
local IMPORT_STATEMENT_PATTERNS = { 'require'..POSSIBLE_CHAR_PATTERN, 'mw.loadData'..POSSIBLE_CHAR_PATTERN }
local DEV_WIKI_URL = 'https://dev.fandom.com/wiki/'
--- Denotes whether or not clustering of nodes will occur
-- @member {boolean} p.enableClusters
p.enableClusters = false -- By default, clustering of submodules with their main modules is disabled
--- Returns a set of this wiki's module pages.
-- @function getModuleSet
-- @param {string} dplResult HTML of result returned by DPL parser function
-- @returns {table} Set of module page names on this wiki
local function getModuleSet(dplResult)
local moduleSet = {}
for moduleName in mw.ustring.gmatch(dplResult, MODULE_NAME_PATTERN) do
-- Ignoring documentation subpages
if (string.find(moduleName, '/doc') == nil) then
moduleSet[moduleName] = 0
end
end
return moduleSet
end
--- Returns a table of each module's dependencies.
-- @function getModuleDependencies
-- @param {string} moduleSet Set of module page names on this wiki
-- @returns {table} Map of modules and their dependencies inside a set
local function getModuleDependencies(moduleSet)
local moduleDependencies = {} -- mapping modules with their dependencies
-- Initializing table entries
for moduleName, _ in pairs(moduleSet) do
-- Ignoring documentation subpages
moduleDependencies[moduleName] = {}
end
-- Finding dependencies
for moduleName, _ in Table.skpairs(moduleSet) do
local moduleCode = mw.title.new(moduleName):getContent()
assert(moduleCode ~= nil, '"'..moduleName..'" does not exist\n'..mw.dumpObject(moduleDependencies))
-- Define a Lua module dependency as one that is imported using
-- require() or mw.loadData() functions
-- First, find all import statements in module code
for _, importStatementPattern in ipairs(IMPORT_STATEMENT_PATTERNS) do
for importStatement in mw.ustring.gmatch(moduleCode, importStatementPattern) do
-- Second, extract the module names from import statements
for dependency in mw.ustring.gmatch(importStatement, MODULE_NAME_PATTERN) do
moduleDependencies[moduleName][dependency] = 0
end
-- For modules imported from Dev wiki
for dependency in mw.ustring.gmatch(importStatement, DEV_MODULE_NAME_PATTERN) do
moduleDependencies[moduleName][dependency] = 0
end
end
end
end
return moduleDependencies
end
--- Builds a map of each main module's subpages.
-- @function getModuleSubpageMap
-- @param {table} moduleSet Set of modules on this wiki including submodules
-- @returns {table} Map of main modules' root text to a table of the full names of their submodules (including main module)
local function getModuleSubpageMap(moduleSet)
local subpageMap = {}
for moduleName, _ in Table.skpairs(moduleSet) do
local title = mw.title.new(moduleName)
local rootText = title['rootText']
if (subpageMap[rootText] == nil) then
subpageMap[rootText] = {}
end
table.insert(subpageMap[rootText], moduleName)
end
return subpageMap
end
--- Builds a directed graph visualization in the form of a DOT file.
-- @function buildDOTOutput
-- @param {table} moduleDependencies Map of modules and their dependencies
-- @param {table} subpageMap Map of main modules and their submodules
-- @returns {string} DOT output
local function buildDOTOutput(moduleDependencies, subpageMap)
local dotResult = { 'strict digraph G {' }
local nodeTemplate = '\t"%s" [label="%s\\n# dep.: %d", URL="%s"]'
-- Initializing nodes
for moduleName, dependencies in Table.skpairs(moduleDependencies) do
local canonicalUrl = tostring(mw.uri.canonicalUrl(moduleName))
local dependencyCount = Table.size(dependencies)
table.insert(dotResult, string.format(nodeTemplate, moduleName, moduleName, dependencyCount, canonicalUrl))
end
if (p.enableClusters) then
-- Adding clusters based on root text (e.g. "Module:Weapons" and "Module:Weapons/data"
-- will be in the same cluster since they both have "Weapons")
for rootText, subpages in Table.skpairs(subpageMap) do
local moduleSubpages = { '\tsubgraph "cluster_'..rootText..'" {' }
for _, subpage in Table.skpairs(subpages) do
table.insert(moduleSubpages, '"'..subpage..'"')
end
table.insert(moduleSubpages, '}')
table.insert(dotResult, table.concat(moduleSubpages, ' '))
end
end
-- Adding graph edges
for moduleName, dependencies in Table.skpairs(moduleDependencies) do
local graphEdges = { '\t"'..moduleName..'" -> {' }
for dependency, _ in pairs(dependencies) do
table.insert(graphEdges, '"'..dependency..'"')
-- Adding additional nodes of modules from dev wiki as DPL will not
-- get them since they are not located on this wiki
if (string.find(dependency, 'Dev:') ~= nil) then
local canonicalUrl = DEV_WIKI_URL..string.gsub(dependency, 'Dev:', 'Module:')
-- Dev modules have 0 dependencies from this wiki
table.insert(dotResult, string.format(nodeTemplate, dependency, dependency, 0, canonicalUrl))
end
end
table.insert(graphEdges, '}')
table.insert(dotResult, table.concat(graphEdges, ' '))
end
table.insert(dotResult, '}')
return table.concat(dotResult, '\n')
end
--- Entry point of program.
-- @function p.main
-- @param {table} frame Frame object
-- @returns {string} Preformatted text of resultant DOT graph
function p.main(frame)
-- Any argument assigned to "cluster" when module invoked will enable clustering
p.enableClusters = (frame.args['cluster'] and true)
-- TODO: Replace the below statement with call of Extension:DynamicPageListEngine's
-- mw.ext.dpl.getPages() if extension is available on your wiki, ignore this
-- TODO otherwise
local dplResult = mw.getCurrentFrame():preprocess('{{#dpl:|namespace='..MODULE_LOCALIZATION..'}}')
local moduleSet = getModuleSet(dplResult)
local subpageMap = getModuleSubpageMap(moduleSet)
local moduleDependencies = getModuleDependencies(moduleSet)
return '<pre>\n'..buildDOTOutput(moduleDependencies, subpageMap)..'\n</pre>'
end
return p