Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
luacheck:
name: Luacheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nebularg/actions-luacheck@v1
with:
files: '*.lua'
args: '--no-color -q'

toc-validation:
name: TOC validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify TOC file references exist
run: |
EXIT_CODE=0
while IFS= read -r line; do
line="$(echo "$line" | sed 's/\r$//')"
[[ -z "$line" ]] && continue
[[ "$line" =~ ^## ]] && continue
filepath="$(echo "$line" | tr '\\' '/')"
if [[ ! -f "$filepath" ]]; then
echo "FAIL: $filepath listed in .toc but does not exist"
EXIT_CODE=1
fi
done < EasyFind.toc
exit $EXIT_CODE

commit-hygiene:
name: Commit hygiene
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Validate commit messages
run: |
BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"
EXIT_CODE=0

while IFS= read -r sha; do
MSG="$(git log --format='%B' -n 1 "$sha")"
SUBJECT="$(echo "$MSG" | head -n 1)"

if [[ -z "$SUBJECT" ]]; then
echo "FAIL [$sha]: Empty subject line"
EXIT_CODE=1
continue
fi

if [[ ${#SUBJECT} -gt 72 ]]; then
echo "FAIL [$sha]: Subject exceeds 72 chars (${#SUBJECT})"
EXIT_CODE=1
fi

done < <(git rev-list "$BASE".."$HEAD")

exit $EXIT_CODE

file-hygiene:
name: File hygiene
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for prohibited files
run: |
EXIT_CODE=0

# Block .env files
ENV_FILES=$(find . -name '.env' -o -name '.env.*' | grep -v '.env.example' | grep -v '.git/' || true)
if [[ -n "$ENV_FILES" ]]; then
echo "FAIL: .env file(s) in repository: $ENV_FILES"
EXIT_CODE=1
fi

# Block credential files
SECRET_FILES=$(find . -not -path './.git/*' -iregex '.*\.\(key\|pem\|p12\|pfx\)$' || true)
if [[ -n "$SECRET_FILES" ]]; then
echo "FAIL: Credential file(s) found: $SECRET_FILES"
EXIT_CODE=1
fi

# Check for hardcoded secrets in Lua files
SECRET_PATTERNS=$(grep -rlE '(api[_-]?key|secret|token|password)\s*[:=]\s*["'"'"'][A-Za-z0-9+/=_-]{20,}' *.lua Locales/*.lua 2>/dev/null || true)
if [[ -n "$SECRET_PATTERNS" ]]; then
echo "FAIL: Possible hardcoded secret in: $SECRET_PATTERNS"
EXIT_CODE=1
fi

exit $EXIT_CODE
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Release artifacts
*.zip

# Editor files
*.swp
*.swo
*~

# OS files
Thumbs.db
.DS_Store
82 changes: 82 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
std = "lua51"
max_line_length = false

-- Suppress warnings that are standard WoW addon patterns, not real issues
ignore = {
"431", -- shadowing upvalue (self in nested callbacks is standard WoW pattern)
"432", -- shadowing upvalue argument
}

-- Globals this addon sets
globals = {
"EasyFind",
"EasyFindDB",
"EasyFind_OnAddonCompartmentClick",
"SlashCmdList",
"StaticPopupDialogs",
"SLASH_EASYFIND1",
"BINDING_NAME_EASYFIND_TOGGLE",
"BINDING_NAME_EASYFIND_FOCUS",
"BINDING_NAME_EASYFIND_TOGGLE_FOCUS",
"BINDING_NAME_EASYFIND_CLEAR",
}

-- WoW API globals (read-only)
read_globals = {
-- WoW Lua extensions
"debugstack", "strsplit", "strtrim", "wipe", "hooksecurefunc",
"format", "time", "date",

-- Core API
"CreateFrame", "CreateFont", "CreateVector2D",
"GetTime", "GetLocale", "GetCVar", "GetCursorPosition",
"GetAddOnMetadata", "GetAtlasInfo", "GetMinimapShape",
"GetBindingKey", "GetCurrentBindingSet", "SaveBindings", "SetBinding",
"GetCategoryInfo", "GetPlayerFacing",
"SetPortraitTexture", "ToggleWorldMap", "ToggleDropDownMenu",
"InterfaceOptions_AddCategory", "InCombatLockdown",
"IsShiftKeyDown", "IsMouseButtonDown", "IsAltKeyDown", "IsControlKeyDown",
"IsInGroup", "IsInInstance", "IsIndoors", "UnitIsGroupLeader",
"UnitFactionGroup", "UnitPosition",
"StaticPopup_Show", "GameTooltip_Hide", "PlaySound", "ReloadUI",
"GetSpellInfo", "GetItemInfo", "UseToyByItemID",
"PanelTemplates_GetSelectedTab",

-- Frames and UI objects
"UIParent", "GameTooltip", "WorldMapFrame", "Minimap", "MinimapCluster",
"CharacterFrame", "PaperDollFrame", "AchievementFrame",
"CharacterStatsPane", "PaperDollTitlesPane", "PaperDollEquipmentManagerPane",
"CurrencyFrame",
"SpellBookFrame", "PlayerSpellsFrame", "CollectionsJournal",
"EncounterJournal", "PVEFrame", "ReputationFrame", "TokenFrame",
"GroupFinderFrame", "LFGListFrame", "HelpFrame", "ClassTalentFrame",
"GuildMicroButton", "StoreMicroButton", "PlayerFrame", "StoreFrame",
"LFDParentFrame", "RaidFinderFrame",
"LFGListPVEStub", "LFGListPVPStub",
"HonorFrame", "ConquestFrame", "TrainingGroundsFrame",
"PVPQueueFrame",
"AchievementFrameCategories_ExpandToCategory",
"AchievementFrameCategories_UpdateDataProvider",
"Menu", "ScrollBoxConstants",

-- C_* namespaces
"C_AddOns", "C_AchievementInfo", "C_AreaPoiInfo", "C_CurrencyInfo",
"C_EncounterJournal", "C_GossipInfo", "C_MajorFactions", "C_Map",
"C_Minimap", "C_MountJournal", "C_Navigation", "C_PetJournal",
"C_Reputation", "C_SuperTrack", "C_TaxiMap", "C_Texture", "C_Timer",
"C_ToyBox", "C_VignetteInfo",

-- Constants, Enums, Mixins
"Enum", "Settings", "BackdropTemplateMixin",
"SOUNDKIT", "UIDROPDOWNMENU_OPEN_MENU", "UISpecialFrames",
"LE_PET_JOURNAL_FILTER_COLLECTED", "LE_PET_JOURNAL_FILTER_NOT_COLLECTED",

-- Font objects
"Game15Font_Shadow", "GameFontNormal", "GameFontNormalSmall",
"GameFontHighlight", "GameFontHighlightSmall", "GameFontDisable",
"GameFontDisableSmall", "GameFontNormalLarge",
}

-- WoW callbacks have fixed signatures; unused args are normal
unused_args = false
self = false
10 changes: 5 additions & 5 deletions Core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -426,29 +426,29 @@ function EasyFind:TestIndicatorTexture(texturePath)
insets = { left = 11, right = 12, top = 12, bottom = 11 }
})
testFrame:SetBackdropColor(0, 0, 0, 0.9)

if not testFrame.texture then
testFrame.texture = testFrame:CreateTexture(nil, "ARTWORK")
testFrame.texture:SetSize(200, 200)
testFrame.texture:SetPoint("CENTER")
end

if not testFrame.title then
testFrame.title = testFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
testFrame.title:SetPoint("TOP", 0, -15)
end

if not testFrame.closeBtn then
testFrame.closeBtn = CreateFrame("Button", nil, testFrame, "UIPanelCloseButton")
testFrame.closeBtn:SetPoint("TOPRIGHT", -5, -5)
end

-- Try to load the texture
testFrame.texture:SetTexture(texturePath)
testFrame.texture:SetVertexColor(ns.YELLOW_HIGHLIGHT[1], ns.YELLOW_HIGHLIGHT[2], ns.YELLOW_HIGHLIGHT[3], 1)
testFrame.title:SetText("Testing: " .. texturePath)
testFrame:Show()

EasyFind:Print("Testing texture: " .. texturePath)
EasyFind:Print("Close the preview window to dismiss.")
end
Expand Down
6 changes: 3 additions & 3 deletions Database.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1621,7 +1621,7 @@ function Database:ScoreInitials(text, query)
return bonus
end
end

-- Strategy 2: Prefix-of-words - each query segment matches the start of a word
-- "raba" → "ra(ndom) ba(ttleground)" - greedily consume query chars across words
local qi = 1 -- position in query
Expand All @@ -1648,7 +1648,7 @@ function Database:ScoreInitials(text, query)
-- Score based on how many words were matched (more = better abbreviation)
return 110 + mmin(wordsMatched * 3, 20)
end

return 0
end

Expand Down Expand Up @@ -1712,7 +1712,7 @@ function Database:DamerauLevenshtein(s1, s2, len1, len2)
local prev2, prev, curr = dlPrev2, dlPrev, dlCurr

for j = 0, len2 do prev[j] = j end

for i = 1, len1 do
curr[0] = i
local minInRow = i
Expand Down
Loading
Loading