Module:HistoricEnglandSearch
Appearance
local p = {}
-- =========================================================
-- Configuration
-- =========================================================
-- Base URL for dynamic search
local BASE_URL = "https://historicengland.org.uk/listing/the-list/results/"
-- Display labels for categories
local CATEGORY_LABEL = {
Listing = "listed buildings",
Scheduling = "scheduled monuments",
["Park and Garden"] = "registered parks and gardens"
}
-- Valid categories
local VALID_CATEGORIES = {Listing=true, Scheduling=true, ["Park and Garden"]=true}
-- Valid grades
local VALID_GRADES = {["I"]=true, ["II*"]=true, ["II"]=true}
-- Open Data layer mapping
local OPEN_DATA_LAYERS = {
Listing = {layer=0, title="Listed Building Points", website="Listed Building points"},
Scheduling = {layer=6, title="Scheduled Monuments", website="Scheduled Monuments"},
["Park and Garden"] = {layer=7, title="Registered Parks and Gardens", website="Parks and Gardens"}
}
-- URL encoding helper
local function urlencode(str)
return mw.uri.encode(str, "QUERY")
end
-- Normalize category
local function normalizeCategory(cat)
if cat and VALID_CATEGORIES[cat] then
return cat
end
return "Listing"
end
-- =========================================================
-- Geography filter builder
-- =========================================================
local function buildGeography(args, startIndex)
local filters, idx = {}, startIndex or 1
if args.county then
table.insert(filters,
string.format("filters[%d][field]=county&filters[%d][values][0]=%s&filters[%d][type]=all",
idx, idx, urlencode(args.county), idx))
idx = idx + 1
end
if args.district then
table.insert(filters,
string.format("filters[%d][field]=district&filters[%d][values][0]=%s&filters[%d][type]=all",
idx, idx, urlencode(args.district), idx))
idx = idx + 1
end
if args.parish then
table.insert(filters,
string.format("filters[%d][field]=parish&filters[%d][values][0]=%s&filters[%d][type]=all",
idx, idx, urlencode(args.parish), idx))
idx = idx + 1
end
return filters, idx
end
-- =========================================================
-- Grade filter builder
-- =========================================================
local function buildGrade(args, category, startIndex, warnings)
local idx = startIndex or 0
local gradeUsed = nil
if args.grade then
if VALID_GRADES[args.grade] and (category=="Listing" or category=="Park and Garden") then
gradeUsed = args.grade
return string.format(
"filters[%d][field]=grade&filters[%d][values][0]=%s&filters[%d][type]=all",
idx, idx, urlencode(args.grade), idx
), gradeUsed
else
table.insert(warnings, "Grade ignored (invalid or not applicable to category)")
end
end
return nil, nil
end
-- =========================================================
-- Main invocation
-- =========================================================
function p.main(frame)
local args = frame:getParent().args
local warnings = {}
-- -------------------------------
-- Open Data citation mode
-- -------------------------------
if args.opendata then
local category = normalizeCategory(args.category)
local data = OPEN_DATA_LAYERS[category] or OPEN_DATA_LAYERS.Listing
if not args.date then
table.insert(warnings, "Missing date for Open Data citation")
end
local cite = frame:expandTemplate{
title = "cite web",
args = {
url = "https://opendata-historicengland.hub.arcgis.com/datasets/historicengland::national-heritage-list-for-england-nhle?layer="..data.layer,
title = data.title ,
website = "National Heritage List for England, NHLE",
publisher = "Historic England",
date = args.date,
["access-date"] = args["access-date"]
}
}
-- Keep only real warnings
local realWarnings = {}
for _, w in ipairs(warnings) do
if w:find("ignored") or w:find("missing") then
table.insert(realWarnings, w)
end
end
if #realWarnings > 0 then
cite = cite .. frame:extensionTag{name="comment", content=table.concat(realWarnings,"; ")}
end
return cite
end
-- -------------------------------
-- Dynamic search link mode
-- -------------------------------
local category = normalizeCategory(args.category)
local params = {}
table.insert(params, "size=n_96_n")
-- Category filter
local filterIndex = 0
table.insert(params,
string.format(
"filters[%d][field]=category&filters[%d][values][0]=%s&filters[%d][type]=any",
filterIndex, filterIndex, urlencode(category), filterIndex
)
)
filterIndex = filterIndex + 1
-- Geography filters
local geoFilters, nextIndex = buildGeography(args, filterIndex)
for _, f in ipairs(geoFilters) do
table.insert(params, f)
end
-- Grade filter
local gradeFilter, gradeUsed = buildGrade(args, category, nextIndex, warnings)
if gradeFilter then
table.insert(params, gradeFilter)
nextIndex = nextIndex + 1
end
-- Sorting
table.insert(params, "sort-field=name")
table.insert(params, "sort-direction=asc")
local url = BASE_URL .. "?" .. table.concat(params,"&")
-- Citation title
local label = CATEGORY_LABEL[category] or "heritage assets"
local display = args.display or ""
local title
if gradeUsed and (category=="Listing" or category=="Park and Garden") then
title = "Historic England search link for Grade " .. gradeUsed .. " " .. label
else
title = "Historic England search link for " .. label
end
if display ~= "" then
title = title .. " in " .. display
end
local cite = frame:expandTemplate{
title = "cite web",
args = {
url = url,
title = title,
website = "Search the National Heritage List for England",
publisher = "Historic England",
date = args.date,
["access-date"] = args["access-date"]
}
}
-- Keep only real warnings
local realWarnings = {}
for _, w in ipairs(warnings) do
if w:find("ignored") or w:find("missing") then
table.insert(realWarnings, w)
end
end
if #realWarnings > 0 then
cite = cite .. frame:extensionTag{name="comment", content=table.concat(realWarnings,"; ")}
end
return cite
end
return p