wowlua init turns an existing addon into a wowlua project without changing
its code. For an addon built with the BigWigs packager, init also converts
.pkgmeta, and the build matches the packager's: the same loaded code, the
same shipped files, line endings and TOC versions. This is checked on 36
addons, including BigWigs, DBM, WeakAuras, ElvUI and Details.
Run it
Run init in the addon's folder, best with a clean Git working tree. Inside a
Git repository, files are moved with git mv, so their history follows them.
cd MyAddonwowlua init --from-pkgmeta # TOCs and .pkgmeta → wowlua.jsonwowlua build --release # compare with the packager's zipwowlua publish --dry-run # see what would be uploaded.pkgmeta (or pkgmeta.yaml) is converted whenever it exists.
--from-pkgmeta makes it required, and --from-pkgmeta <file> names another
packager project file. An addon without .pkgmeta is adopted from its TOC
files alone with wowlua init; --from-toc <file> picks the TOC.
An example
Tally is a small addon with a retail and a Classic Era TOC, three Ace3 libraries as packager externals, and a release workflow that runs the packager:
Tally/├── .github/workflows/release.yml runs BigWigsMods/packager@v2├── .pkgmeta├── Tally.toc ## Interface: 120100├── Tally_Vanilla.toc ## Interface: 11509├── embeds.xml├── Locale.lua├── Core.lua└── Media/icon.tgapackage-as: Tally externals: Libs/LibStub: https://repos.wowace.com/wow/libstub/tags/1.0 Libs/CallbackHandler-1.0: https://repos.wowace.com/wow/callbackhandler/trunk/CallbackHandler-1.0 Libs/AceAddon-3.0: https://repos.wowace.com/wow/ace3/trunk/AceAddon-3.0 Libs/AceEvent-3.0: https://repos.wowace.com/wow/ace3/trunk/AceEvent-3.0 ignore: - README.md manual-changelog: CHANGELOG.mdwowlua init --from-pkgmeta adopts it:
Adopted Tally for standard, vanilla (3 files moved into src/, 0 in-game paths updated) Converted 4 externals from .pkgmeta Note TOC files are generated from wowlua.json now; the old Tally.toc, Tally_Vanilla.toc can be deleted Note .github/workflows/release.yml publishes with the BigWigs packager, which keeps working; to publish with wowlua, replace its packager steps with one - uses: DomenikIrrgang/wowlua/.github/actions/setup-wowlua@main - run: wowlua publish env: # the packager step's env (CF_API_TOKEN, WOWI_API_TOKEN, WAGO_API_TOKEN, GITHUB_OAUTH)(runs with `-d`, which upload nothing, become `wowlua package`)The Lua and XML files moved into src/. The textures stayed where they were.
The new wowlua.json holds what the TOCs and .pkgmeta said; in part:
{ "addon": { "title": "Tally", "notes": "Counts your kills.", "saved-variables": ["TallyDB"] }, "flavors": { "standard": {}, "vanilla": {} }, "build": { "assets": ["Media/**/*.{tga,blp,png,jpg,jpeg,ogg,mp3,wav,ttf,otf}"], "load-order": ["src/embeds.xml", "src/Locale.lua", "src/Core.lua"], "libs-dir": "Libs", "exclude": ["README.md/**", "README.md"] }, "dependencies": { "aceaddon-3-0": { "svn": "https://repos.wowace.com/wow/ace3/trunk/AceAddon-3.0", "kind": "lua-library", "curseforge-slug": "ace3", "install-path": "AceAddon-3.0", "files": ["AceAddon-3.0.xml"] } }, "compat": { "packager-keywords": true, "line-endings": "crlf", "toc-version": "@project-version@" }}The full file also has the other three dependencies, CurseForge and Wago
publish targets from the TOCs' X-Curse-Project-ID and X-Wago-ID, the
changelog, and a release profile without bundling, minification or
optimizations, like the packager's zip.
The first build fetches the externals into the global cache and locks them in
wowlua.lock:
Updating https://repos.wowace.com/wow/libstub/tags/1.0 Fetching https://repos.wowace.com/wow/libstub/tags/1.0@90 Updating https://repos.wowace.com/wow/callbackhandler/trunk/CallbackHandler-1.0 Fetching https://repos.wowace.com/wow/callbackhandler/trunk/CallbackHandler-1.0@26 Updating https://repos.wowace.com/wow/ace3/trunk/AceAddon-3.0 Fetching https://repos.wowace.com/wow/ace3/trunk/AceAddon-3.0@1284 Updating https://repos.wowace.com/wow/ace3/trunk/AceEvent-3.0 Fetching https://repos.wowace.com/wow/ace3/trunk/AceEvent-3.0@1202warning[W4306]: embedded libraries without a recognizable license file or header: callbackhandler-1-0, aceaddon-3-0, aceevent-3-0 = help: check their licenses before publishing; `lua-library.license-files` can name the file warning: 1 warning emitted Finished Tally 1.0.0-alpha+bccb7af (release: standard, vanilla) in 36.16s → dist/release/Tallydist/release/Tally/ has the generated TOC, src/, the four libraries under
Libs/, Media/, CHANGELOG.md and LICENSES.txt. With the v1.0.0 tag, the
TOC's @project-version@ became ## Version: v1.0.0, as the packager writes
it. Add dist/ to .gitignore: init does not.
What init does
- Reads every TOC the client finds in the folder (
<Folder>.tocand the flavor suffixes, the legacy ones included) and takes the metadata, the interface versions (which give the flavors), SavedVariables, dependencies andX-fields intowowlua.json. - Moves every Lua and XML file the TOCs load into
src/and rewrites absolute in-game paths to them (Interface\AddOns\<Name>\…). Textures, sounds and fonts stay where they are and becomebuild.assets, so their paths do not change. If the addon already has asrcfolder, the sources go towowlua-src/. - Records the existing file order in
build.load-order, per flavor where the TOCs differ, so the build loads files as before. - Records files that only some flavors load in
build.flavor-files, and metadata that differs between flavors as flavor overrides. - Reads
## X-Curse-Project-ID,## X-Wago-IDand## X-WoWI-IDinto publish targets. - Pins the interface numbers in
wowlua.lock, so the first build writes the same## Interfacelines. - Leaves the contents of your
.luafiles alone, apart from those path rewrites. - Leaves the old TOC files in place. TOCs are generated from now on; delete the old ones when you no longer need them.
Lua and XML files that no TOC loads are listed in a warning and left in place. Every step, with its edge cases, is in CLI §12.6.
How .pkgmeta maps to wowlua.json
.pkgmeta |
wowlua.json |
|---|---|
externals |
dependencies, with build.libs-dir and an install-path each |
ignore |
build.exclude |
plain-copy |
build.assets |
package-as |
addon.name |
manual-changelog |
publish.changelog |
move-folders |
workspace members, or workspace.external-addons |
license-output |
compat.license-output |
changelog-title |
compat.changelog-title |
enable-nolib-creation |
compat.nolib-package |
wowi-convert-changelog, wowi-create-changelog, wowi-archive-previous |
the WoWInterface target's changelog-output, changelog and archive-previous |
required-dependencies, optional-dependencies, embedded-libraries, tools-used |
CurseForge relations |
git, SVN and zip externals convert. URLs are read the way the packager reads
them: old CurseForge URLs, SVN trunk and tags/ paths, and sub-paths of
CurseForge and GitHub git URLs. hg externals are listed with W4333 and need a
git mirror or an archive instead. A repository whose addons all come from
move-folders, such as WeakAuras, DBM or ElvUI, becomes a workspace.
Building like the packager
The compat settings init writes keep the build identical to the
packager's (Manifest §9.14):
packager-keywordsapplies the packager's keyword substitution to passthrough Lua and XML files:@project-version@,@debug@blocks,@retail@and the other flavor blocks.initturns it on when your files use them.line-endingsandtoc-versionkeep the packager's line endings and TOCVersion.- The
releaseprofile builds unbundled and unminified. Remove those overrides fromprofiles.releasewhen you want bundled, minified release builds (Optimization).
You can keep .pkgmeta as the source of truth for dependencies and
publishing instead of converting it, with "compat": { "pkgmeta": true }.
The manifest then only adds wowlua's own settings; a key both files set is
E4005.
Your CI keeps working
init leaves .github/workflows untouched, so workflows that run the
packager keep publishing. For each one, it prints how to switch: the packager
steps become setup-wowlua and one wowlua publish with the same env, and
runs with -d become wowlua package.
A converted project publishes the way the packager does. There is no clean
working tree check, the targets upload in the packager's order (CurseForge,
WoWInterface, Wago, GitHub), a target without a token is skipped with a note,
and tokens come from the packager's environment variables (CF_API_KEY or
CF_API_TOKEN, WAGO_API_TOKEN, WOWI_API_TOKEN, GITHUB_OAUTH, …; not
GITHUB_TOKEN) and from its .env file, so existing CI secrets keep working.
Without tokens, a dry run of Tally looks like this:
wowlua publish --dry-run Packaged Tally-v1.0.0.zip (release) → dist/packages/Tally-v1.0.0.zip Skipped curseforge (Tally-v1.0.0.zip): no token (`CF_API_TOKEN`) Skipped wago (Tally-v1.0.0.zip): no token (`WAGO_API_TOKEN`)warning[W4306]: embedded libraries without a recognizable license file or header: callbackhandler-1-0, aceaddon-3-0, aceevent-3-0 = help: check their licenses before publishing; `lua-library.license-files` can name the file warning: 1 warning emitted Finished publishing in 0.20sSee Publishing §11.9 and §11.1.3 for the details.
Then, file by file
The addon builds as it is. Try it in the game with wowlua dev (see
Getting started) and with the
dev window.
When you want types for a file, rename it to .wowlua. In a file that uses no
wowlua syntax, name and type errors are only warnings, so a renamed file
builds as before; they become errors once the file uses wowlua syntax. To
type-check the remaining .lua files too, with warnings only, set
"check": { "lua": true }.
LuaLS ---@ annotations convert into a .d.wowlua declaration file, from
one file or a folder:
wowlua types convert src # writes src.d.wowlua