eliote / simpleaddonmanager Goto Github PK
View Code? Open in Web Editor NEWA simple to use Addon Manager with profile, search, category filter, and more.
Home Page: https://www.curseforge.com/wow/addons/simple-addon-manager
License: MIT License
A simple to use Addon Manager with profile, search, category filter, and more.
Home Page: https://www.curseforge.com/wow/addons/simple-addon-manager
License: MIT License
The text entry box (e.g. when creating a new category) is ignoring the Return keystroke (Enter doesn't work either).
What I expected was that Return (and optionally Enter) works as confirmation, i.e. the same as clicking the OK button with the mouse.
(I'm on a Mac, so there is a slight chance that this is a Mac-specific issue.)
Similar for non-text dialog boxes (like the confirmations for saving), though here I don't know if it is intentional or not, as many addons do ignore the Return key for non-text dialogs. (Escape though works.)
The confirmation dialog when saving a set ('profile') is a very good thing, but I think it isn't really necessary when loading a set. Especially since you explicitly display the set name in the save dialog box (which is also a very good thing). So, if I accidentally load the wrong set, make changes, then I will see in the save dialog box that I had changed the wrong set.
– Tom
When I select 'Enable this addon and its dependencies' from the contextual menu I get attempt to call method 'EnableAddon' (a nil value)
1x SimpleAddonManager/AddonListFrame.lua:57: attempt to call method 'EnableAddon' (a nil value)
[string "@SimpleAddonManager/AddonListFrame.lua"]:57: in function <SimpleAddonManager/AddonListFrame.lua:53>
[string "@SimpleAddonManager/AddonListFrame.lua"]:115: in function `func'
[string "@SimpleAddonManager/Libs/ElioteDropDownMenu-1.0-11/ElioteDropDownMenu-1.0.lua"]:1245: in function <...bs/ElioteDropDownMenu-1.0/ElioteDropDownMenu-1.0.lua:1211>
Locals:
addonIndex = "ArmoryGuildBank"
requiredDeps = <table> {
1 = "Armory"
}
(for generator) = <function> defined =[C]:-1
(for state) = <table> {
1 = "Armory"
}
(for control) = 1
_ = 1
depName = "Armory"
(*temporary) = nil
(*temporary) = SimpleAddonManager {
0 = <userdata>
DidAddonStateChanged = <function> defined @SimpleAddonManager/MainFrame.lua:30
DisableAllAddOns = <function> defined @SimpleAddonManager/Core.lua:304
GetTitleText = <function> defined @SharedXML/PortraitFrame.lua:28
SetPortraitTexCoord = <function> defined @SharedXML/PortraitFrame.lua:87
GetDb = <function> defined @SimpleAddonManager/Core.lua:39
EnableAddOn = <function> defined @SimpleAddonManager/Core.lua:289
CATEGORY_SIZE_W = 250
GetPlayerInfo = <function> defined @SimpleAddonManager/Core.lua:311
TitleContainer = Frame {
}
UpdateOkButton = <function> defined @SimpleAddonManager/MainFrame.lua:48
ValidateCategoryName = <function> defined @SimpleAddonManager/CategoryFrame.lua:355
IsAddonInstalled = <function> defined @SimpleAddonManager/Core.lua:284
RegisterModule = <function> defined @SimpleAddonManager/Core.lua:262
ADDON_LOADED = <function> defined @SimpleAddonManager/Core.lua:334
SetCharacter = <function> defined @SimpleAddonManager/Core.lua:179
CategoryFrame = Frame {
}
MIN_SIZE_W = 470
HookMenuButton = <function> defined @SimpleAddonManager/Core.lua:381
CancelButton = Button {
}
SetPortraitAtlasRaw = <function> defined @SharedXML/PortraitFrame.lua:83
Bg = SimpleAddonManagerBg {
}
initialized = true
ShowConfirmDialog = <function> defined @SimpleAddonManager/Core.lua:154
NineSlice = Frame {
}
SetPortraitTextureSizeAndOffset = <function> defined @SharedXML/PortraitFrame.lua:95
GetCharacter = <function> defined @SimpleAddonManager/Core.lua:175
edited = true
CategoryButton = Button {
}
SearchBox = EditBox {
}
SetCategoryVisibility = <function> defined @SimpleAddonManager/CategoryFrame.lua:384
PLAYER_ENTERING_WORLD = <function> defined @SimpleAddonManager/Core.lua:365
IsAddonCollapsed = <function> defined @SimpleAddonManager/Filters.lua:163
ShowInputDialog = <function> defined @SimpleAddonManager/Core.lua:140
SetPortraitShown = <function> defined @SharedXML/PortraitFrame.lua:91
GetModule = <function> defined @SimpleAddonManager/Core.lua:271
ResultOptionsButton = Button {
}
DisableAllButton = Button {
}
EnableAllButton = Button {
}
OkButton = Button {
}
CharacterDropDown = SAM_CharacterDropDown {
}
ScrollFrame = ScrollFrame {
}
SetPortraitTextureRaw = <function> defined @SharedXML/PortraitFrame.lua:79
Sizer = Button {
}
SetsButton = Button {
}
ConfigButton = Button {
}
isMenuHooked = true
ShowDialog = <function> defined @SimpleAddonManager/Core.lua:106
UpdateCategoryFrame = <function> defined @SimpleAddonManager/CategoryFrame.lua:378
EnableAllAddOns = <function> defined @SimpleAddonManager/Core.lua:299
MIN_SIZE_H = 400
DisableAddOn = <function> defined @SimpleAddonManager/Core.lua:294
SetTitleMaxLinesAndHeight = <function> defined @SharedXML/PortraitFrame.lua:49
Initialize = <function> defined @SimpleAddonManager/Core.lua:200
GetCategoryTable = <function> defined @SimpleAddonManager/CategoryFrame.lua:362
DefaultPortraitTextureSizeAndOffset = <function> defined @SharedXML/PortraitFrame.lua:101
LocalizeCategoryName = <function> defined @SimpleAddonManager/CategoryFrame.lua:329
UpdateMemoryTickerPeriod = <function> defined @SimpleAddonManager/AddonListFrame.lua:404
UpdateListFilters = <function> defined @SimpleAddonManager/Filters.lua:300
Ge
Would be great to have the possibility to assign a custom category recursively to all dependencies, instead of having to right-click each one.
For example, for things like this:
This could be done, for example, via modifier key: If I assign the category "Map" via context menu to the top-level item ("HandyNotes") while holding down the Shift key, "Maps" would be assigned – additively – to all its children.
The same for removing a category assignment.
Would be useful mainly in the category setup process, to quickly see, without right-clicking, if I have applied the category. (But also later for certain addons, where the description is so poor that you have no clue what this thing was for ;)
Like this:
Thanks for considering,
– Tom
Edit: Replaced example image for recursive categories with a better one.
Hi. Please add option when showing addons list will always show for current character only. It is implemented in LeatrixPlus and it is very useful.
When I installed your addon, I got this option disappeared and it is become very usefulness.
How it look in LeatrixPlus:
if LeaPlusLC["CharAddonList"] == "On" then
-- Set the addon list to character by default
if AddonCharacterDropDown and AddonCharacterDropDown.selectedValue then
AddonCharacterDropDown.selectedValue = UnitName("player");
AddonCharacterDropDownText:SetText(UnitName("player"))
end
end
Message: ...terface/AddOns/SimpleAddonManager/AddonListFrame.lua:321: bad argument #1 to 'GetAddOnMetadata' (Invalid AddOn name ElvUI. - Usage: local value = C_AddOns.GetAddOnMetadata(name, variable))
Time: Mon May 22 16:42:40 2023
Count: 1
Stack: ...terface/AddOns/SimpleAddonManager/AddonListFrame.lua:321: bad argument #1 to 'GetAddOnMetadata' (Invalid AddOn name ElvUI. - Usage: local value = C_AddOns.GetAddOnMetadata(name, variable))
[string "=[C]"]: in function `GetAddOnMetadata'
[string "@Interface/AddOns/SimpleAddonManager/AddonListFrame.lua"]:321: in function `update'
[string "@Interface/AddOns/SimpleAddonManager/Filters.lua"]:305: in function `UpdateListFilters'
[string "@Interface/AddOns/SimpleAddonManager/Core.lua"]:224: in function `Update'
[string "@Interface/AddOns/SimpleAddonManager/Core.lua"]:231: in function <Interface/AddOns/SimpleAddonManager/Core.lua:229>
[string "=[C]"]: ?
[string "=[C]"]: in function `Show'
[string "@Interface/FrameXML/UIParent.lua"]:3246: in function `ShowUIPanel'
[string "@Interface/AddOns/SimpleAddonManager/Core.lua"]:432: in function <Interface/AddOns/SimpleAddonManager/Core.lua:428>
Locals: (*temporary) = "ElvUI"
(*temporary) = "Version"
(*temporary) = "Invalid AddOn name ElvUI. - Usage: local value = C_AddOns.GetAddOnMetadata(name, variable)"
If you have addons A, B, C loaded and you choose PROFILE_TWO with D, E, F then A, B, C addons are disabled and D,E,F are enabled. My suggestion is to have an option to add PROFILE_TWO's addons D,E,F to A,B,C
Add an auto-generated category that shows only active addons, ignoring enabled addons with missing/disabled dependencies.
Message: Interface/AddOns/SimpleAddonManager/Core.lua:336: bad argument #2 to 'DisableAddOn' (Usage: C_AddOns.DisableAddOn(name [, character]))
Time: Fri Nov 10 09:22:10 2023
Count: 2
Stack: Interface/AddOns/SimpleAddonManager/Core.lua:336: bad argument #2 to 'DisableAddOn' (Usage: C_AddOns.DisableAddOn(name [, character]))
Locals:
Add an auto-generated category for all addons without a category.
Hello Eliote! Thanks for giving us such an wonderful Addon Manager calling SAM.
I'am here to just suggest some minor Features.
Would be wonderful!
Thanks for giving us that Addon to manage all that different Situations in WoW!
Decided to give SAM a try. Installed 1.16 and when I logged in to the game I received the following error. Thanks.
1x SimpleAddonManager/Profile.lua:21: bad argument #1 to 'pairs' (table expected, got nil)
[string "=[C]"]: in function pairs' [string "@SimpleAddonManager/Profile.lua"]:21: in function <SimpleAddonManager/Profile.lua:10> [string "@SimpleAddonManager/Profile.lua"]:333: in function
OnLoad'
[string "@SimpleAddonManager/Core.lua"]:360: in function `?'
[string "@SimpleAddonManager/Core.lua"]:328: in function <SimpleAddonManager/Core.lua:327>
Locals:
(*temporary) = nil
(*temporary) = "table expected, got nil"
= defined =[C]:-1
For informational purposes, 'Show Blizzard addons found in dependencies' is an interesting option. However it comes with a pitfall:
If you have this option enabled and then click 'Disable All' (e.g. if you want to remove all entries from a set), SAM will also disable all displayed Blizz addons, like here for example:
As a result, after reloading/logging, you get a gazillion errors and have no idea what happened.
If at some point it occurs to you that your sudden problem may be related to that option, and you disable now this option and reload with your set, you are making things not better: Since these Blizz addons are likely not part of any of your sets, loading a set will not enable them.
Also clicking 'Enable All' will not help you, as SAM's 'Disable All' / 'Enable All' seems to act on displayed addons (not on all addons as the button label suggests).
To get your disabled Blizz addons back, you have to re-enable the option, then click 'Enable All', and then you can disable the option for good and reload with your set.
Well, once you have learned that, it's no longer an issue, but it can take a while to figure this out ;-)
I think a good solution would be to hard-exclude all Blizz addons from being disabled. Or popping up a fat warning if someone curious like me enables the option ;)
– Tom
I thought it would be a great idea to be able to make subcategories of addons, such as if you had multiple UI addons that do different things, you can have a "Chat" category inside of a "UI" category, and a "Minimaps" category inside of that same "UI" category, essentially nested folders.
This would be great so that all those subcategories could be enabled at the same time when enabling the parent category, so every subcategory within the example UI category would be enabled.
I received this message in the chat:
[12:26 AM] Details!: an addon made your game freeze for more than a half second, use '/details perf' to know more.
and using the command showed this error.
["1"] = "Stuttering Information:",
["2"] = "An addon feature, script is using: _G.UpdateAddOnMemoryUsage()",
["3"] = "",
["4"] = "Description: Calculates memory usage of addons",
["5"] = "",
["6"] = "You may first: disable the addon feature that uses the functionality.",
["7"] = "Second: disable a script which are using the function call: _G.UpdateAddOnMemoryUsage().",
["8"] = "",
["9"] = "Callstack for Debug:",
["10"] = "[string "@Interface/AddOns/SimpleAddonManager/MiniMapButton.lua"]:32: in function `OnTooltipShow'",
["11"] = "[string "@Interface/AddOns/BigWigs/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua"]:73: in function <.../AddOns/BigWigs/Libs/LibDBIcon-1.0/LibDBIcon-1.0.lua:59>",
Unsurprisingly, I do notice now that my game stutters if I mouse over the SAM minimap button.
Hi,
I made the same suggestion on AddonSkin project page, would it be possible to make SAM skinned like Elvui ?
Thanks
Apologies if I missed it but right now when you scroll you move 1 line/addon at a time. Fast scroll would be holding say shift and moving 10 or 25 lines/addons at a time.
When loading a set (profile) via slash command, I often – but not always – get this error:
attempt to index field 'CategoryFrame' (a nil value)
9x SimpleAddonManager/CategoryFrame.lua:379: attempt to index field 'CategoryFrame' (a nil value)
[string "@SimpleAddonManager/CategoryFrame.lua"]:379: in function `UpdateCategoryFrame'
[string "@SimpleAddonManager/Core.lua"]:184: in function `Update'
[string "@SimpleAddonManager/Profile.lua"]:102: in function `LoadAddonsFromProfile'
[string "@SimpleAddonManager/SlashCommand.lua"]:42: in function `func'
[string "@SimpleAddonManager/SlashCommand.lua"]:109: in function `?'
[string "@DataStore/libs/AceConsole-3.0-7/AceConsole-3.0.lua"]:90: in function `?'
[string "@FrameXML/ChatFrame.lua"]:5224: in function `ChatEdit_ParseText'
[string "@FrameXML/ChatFrame.lua"]:4888: in function `ChatEdit_SendText'
[string "@FrameXML/ChatFrame.lua"]:3132: in function <FrameXML/ChatFrame.lua:3125>
[string "=[C]"]: in function `RunMacroText'
[string "@FrameXML/SecureTemplates.lua"]:468: in function `handler'
[string "@FrameXML/SecureTemplates.lua"]:690: in function <FrameXML/SecureTemplates.lua:672>
...
[string "=[C]"]: in function `RunMacroText'
[string "@FrameXML/SecureTemplates.lua"]:468: in function `handler'
[string "@FrameXML/SecureTemplates.lua"]:690: in function <FrameXML/SecureTemplates.lua:672>
[string "@FrameXML/SecureTemplates.lua"]:704: in function <FrameXML/SecureTemplates.lua:697>
[string "@FrameXML/SecureTemplates.lua"]:746: in function <FrameXML/SecureTemplates.lua:730>
[string "=[C]"]: ?
[string "@FrameXML/SecureHandlers.lua"]:266: in function <FrameXML/SecureHandlers.lua:263>
[string "=[C]"]: ?
[string "@FrameXML/SecureHandlers.lua"]:296: in function <FrameXML/SecureHandlers.lua:279>
[string "=(tail call)"]: ?
Locals:
self = SimpleAddonManager {
0 = <userdata>
DidAddonStateChanged = <function> defined @SimpleAddonManager/MainFrame.lua:30
DisableAllAddOns = <function> defined @SimpleAddonManager/Core.lua:304
GetTitleText = <function> defined @SharedXML/PortraitFrame.lua:28
SetPortraitTexCoord = <function> defined @SharedXML/PortraitFrame.lua:87
GetDb = <function> defined @SimpleAddonManager/Core.lua:39
EnableAddOn = <function> defined @SimpleAddonManager/Core.lua:289
CATEGORY_SIZE_W = 250
GetPlayerInfo = <function> defined @SimpleAddonManager/Core.lua:311
TitleContainer = Frame {
}
UpdateOkButton = <function> defined @SimpleAddonManager/MainFrame.lua:48
ValidateCategoryName = <function> defined @SimpleAddonManager/CategoryFrame.lua:355
IsAddonInstalled = <function> defined @SimpleAddonManager/Core.lua:284
RegisterModule = <function> defined @SimpleAddonManager/Core.lua:262
ADDON_LOADED = <function> defined @SimpleAddonManager/Core.lua:334
SetCharacter = <function> defined @SimpleAddonManager/Core.lua:179
MIN_SIZE_W = 470
HookMenuButton = <function> defined @SimpleAddonManager/Core.lua:381
SetPortraitAtlasRaw = <function> defined @SharedXML/PortraitFrame.lua:83
Bg = SimpleAddonManagerBg {
}
ShowConfirmDialog = <function> defined @SimpleAddonManager/Core.lua:154
NineSlice = Frame {
}
SetPortraitTextureSizeAndOffset = <function> defined @SharedXML/PortraitFrame.lua:95
GetCharacter = <function> defined @SimpleAddonManager/Core.lua:175
SetCategoryVisibility = <function> defined @SimpleAddonManager/CategoryFrame.lua:384
PLAYER_ENTERING_WORLD = <function> defined @SimpleAddonManager/Core.lua:365
IsAddonCollapsed = <function> defined @SimpleAddonManager/Filters.lua:163
ShowInputDialog = <function> defined @SimpleAddonManager/Core.lua:140
SetPortraitShown = <function> defined @SharedXML/PortraitFrame.lua:91
GetModule = <function> defined @SimpleAddonManager/Core.lua:271
SetPortraitTextureRaw = <function> defined @SharedXML/PortraitFrame.lua:79
isMenuHooked = true
ShowDialog = <function> defined @SimpleAddonManager/Core.lua:106
UpdateCategoryFrame = <function> defined @SimpleAddonManager/CategoryFrame.lua:378
EnableAllAddOns = <function> defined @SimpleAddonManager/Core.lua:299
MIN_SIZE_H = 400
DisableAddOn = <function> defined @SimpleAddonManager/Core.lua:294
SetTitleMaxLinesAndHeight = <function> defined @SharedXML/PortraitFrame.lua:49
Initialize = <function> defined @SimpleAddonManager/Core.lua:200
GetCategoryTable = <function> defined @SimpleAddonManager/CategoryFrame.lua:362
DefaultPortraitTextureSizeAndOffset = <function> defined @SharedXML/PortraitFrame.lua:101
LocalizeCategoryName = <function> defined @SimpleAddonManager/CategoryFrame.lua:329
UpdateMemoryTickerPeriod = <function> defined @SimpleAddonManager/AddonListFrame.lua:404
UpdateListFilters = <function> defined @SimpleAddonManager/Filters.lua:300
GetAddonsList = <function> defined @SimpleAddonManager/Filters.lua:296
ToggleAddonCollapsed = <function> defined @SimpleAddonManager/Filters.lua:168
SetAddonCollapsed = <function> defined @SimpleAddonManager/Filters.lua:156
FormatMemory = <function> defined @SimpleAddonManager/Core.lua:252
SetBorder = <function> defined @SharedXML/PortraitFrame.lua:62
layoutType = "PortraitFrameTemplate"
DidAnyAddonStateChanged = <function> defined @SimpleAddonManager/MainFrame.lua:40
TableKeysToSortedList = <function> defined @SimpleAddonManage
I'm using the slash commands when logging out, for example in an OPie/M6 macro like this:
#icon inv_10_tailoring_bag2_color4
#label Std
/sam profile '130 Normal Std' ignore
#parse
/logout [mod:meta]
/stopmacro [mod]
/reload
But it can also happen if I enter the slash command manually in the chat. Despite the error, the profile is set correctly.
As said, the error does not appear always. It is possible that it depends on if I had opened the SAM GUI in that session, or if I did a reload somewhere before, not sure.
– Tom
Yeah, I already wanted to suggest the same.
BetterAddonList lets you build nested sets. I really like the neat features of SimpleAddonManager, but without nested sets, honestly, I will probably never use it.
Let me explain why:
In BetterAddonList, the addon tree for my 20 toons looks roughly like this:
Base Set for all
| \
| \
| Some specialized sets
| …
Base Set for
Normal and Support
/ \
/ \
Resting Set Banker Set
| |
Light Set AH toon Set
|
Standard Set
| \
Full Set \
\
PvP Set
As the tree design suggests, these sets are nested: the child sets, lower in the tree, contain all addons of the parent sets they are connected to.
Some examples:
The Base Set contains such basic addons like TinyPad, M6, OPie. The Base Set for Normal and Support contains addons that are needed for all sets, except for the specialized sets (eg WeakAuras, ArkInventory, Bazooka, Leatrix, etc.).
There it branches out to Normal (normal toons) and Support (bankers and AH toons), both based on the Base Set for Normal and Support.
The Resting Set contains addons needed for a normal toon's everyday indoor life (crafting addons, VenturePlan, BrokerAnything, WQAchievements, but also pet battle stuff, etc.). An AH toon doesn't need that stuff.
Based on that, the Light Set is for quick excursions, like killing a rare or two, or a quick Utgarde Pinaccle run for the (damn) mount, therefore it has addons like SilverDragon and Rarity.
Standard Set is for, well, standard stuff like instances or extended world-questing, with addons like Raven, Hekili, TomTom, etc. The Full Set is almost identical but has heavy-weights like Grail/Wholly and is meant for example for doing old questlines for achievements or legendaries and such.
An example for the (only semi-nested) specialized sets is a "Mission table only" set, for non-crafting toons, that has only VenturePlan (plus the Base Set for All, but not the stuff from Base Set for Normal and Support). Or a Torghast set with some specific addons that are useless for anything else.
The main reason for having different addon sets is loading time. My Standard set takes 25-35 seconds to load. When I login just for the mission table, or the AH, I want a short loading screen, hence the smaller sets.
Another reason is technical issues. For example, TSM is notoriously buggy and tends to conflict with other addons, so I would never want to use that on any toon except the AH toons.
The third reason is – and now we come to the point – that with nested sets I can realize all that without much work:) The tree might look complicated, but it isn't.
If an addon manager does not have nested sets, I would have to create each set as standalone set, and the maintenance of the sets would be very time-intensive:
Especially in transition phases between xpacs, like now, I often have to replace a non-working addon by a similar one, until it gets fixed, and then activate the old one again. Without nested sets, I would have to do that for each and every set where the addon is contained. With nested sets, I replace the addon once, in the set where it is contained, and then it gets inherited by the child sets. Simple.
Of course, if you have just 3 toons and a banker, you can probably live with two sets, or even use the Blizz addon manager, but once you have half an army of toons, differentiated – and nested! – sets are a huge help.
– Tom
Originally posted by @tflo in #9 (comment)
Add an option to show the addon list as a dependency tree.
One feature that other some other addon managers of the past have had that I found useful was a feature to mark an addon as required meaning that is should always be enabled. That would be a very nice feature if you can add it. For your addon it would be something like having a profile that would always be enabled in additional to another profile that was selected.
The "load" profile command is helpful if you want to load a bunch of addons, but it would also be great to have an "enable" option like BAL has that doesn't touch the already loaded addons. It just enables the ones listed in the profile and reloads. This allows for doing things very quickly like enabling holiday/event/zone addon sets, without having complete profiles (which include all the addons you normally would use) for each of those situations.
title
By default, when you open the addon manager, all of the addons with dependencies, as so, are automatically open;
There should be a toggle to collapse/uncollapse everything instead of everything being done so individually. Addon Control Panel is an addon that has this feature.
Additionally, an option should be added to automatically load Simple Addon Manager's UI when opened with everything already collapsed, for people like me who hate opening their addon list to see everything expanded out by default.
I'm no WoW addon developer (yet), but is it possible within the WoW API and Lua to read the modification date on the files/folders and then sort by that?
If so, the install date can probably be deduced by logging when the first time an addon is installed.
The reason why I would find this useful is because I sometimes go on addon install binges, but I don't necessarily go immediately in game to test them out. So I'll often forget which addons are the new ones. Often times, the new addons clash or spam me with error messages or tutorial popups, and I just want to sort by modification date and disable all the new addons and then enable them one by one when I feel like it. I know that I could just use profiles for this, but I often change which addons I install so often that I often forget to save my setup as a profile after testing for long enough that everything is good.
I'd be willing to learn and implement this feature myself as a learning experience, but I just don't know if it is viable to do this. Or, if you or someone else implements this, I will definitely look at the commits to learn more about addon development as I did to learn about plugin development for FFXIV. I'm a code contributor for the FFXIV TextToTalk plugin.
As is, when renaming a category, you have to retype the entire previous name if you want to edit the original name in case of a typo, ect.
This is what it shows by default. I think it would be better if the box filled in automatically with what was in there originally, like this;
I found myself renaming categories a few times, like "Levelling" to "Leveling" or "Leveling" to "Leveling & Questing"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.