Fix CP14 heading detection via RoleMap + add manual pass support
- enterprise_pdf_checker.py: resolve custom tag names through PDF RoleMap in _check_headings so PDFs using /Heading1-style tags (mapped to /H1) are correctly detected; add depth guard to walk_tree - js/results.js: add CP14 (Heading Structure) to CP_TO_CHECK; relax H-type restriction so M-type CPs with a linked check also get Mark as Passed / Undo buttons - api.php: add 'Heading Structure' => ['14'] to $check_to_cp for server-side recalculate score with heading override Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2a8db06f0d
commit
dafef834d2
3 changed files with 30 additions and 10 deletions
1
api.php
1
api.php
|
|
@ -1372,6 +1372,7 @@ function handleSaveAdjustedResult() {
|
|||
$check_to_cp = [
|
||||
'Color Contrast' => ['04'],
|
||||
'Image Accessibility' => ['13'],
|
||||
'Heading Structure' => ['14'],
|
||||
];
|
||||
$cp_to_check = [];
|
||||
foreach ($check_to_cp as $checkName => $cpIds) {
|
||||
|
|
|
|||
|
|
@ -1311,22 +1311,41 @@ Respond in JSON format:
|
|||
return
|
||||
|
||||
struct_tree = catalog["/StructTreeRoot"]
|
||||
headings = []
|
||||
if hasattr(struct_tree, 'get_object'):
|
||||
struct_tree = struct_tree.get_object()
|
||||
|
||||
def walk_tree(element):
|
||||
# Load RoleMap so custom tag names (e.g. /Heading1) resolve to standard ones (/H1)
|
||||
role_map = {}
|
||||
if "/RoleMap" in struct_tree:
|
||||
rm = struct_tree["/RoleMap"]
|
||||
if hasattr(rm, 'get_object'):
|
||||
rm = rm.get_object()
|
||||
try:
|
||||
for key, value in rm.items():
|
||||
role_map[str(key)] = str(value)
|
||||
except (AttributeError, TypeError):
|
||||
pass
|
||||
|
||||
headings = []
|
||||
HEADING_TAGS = {"/H1", "/H2", "/H3", "/H4", "/H5", "/H6"}
|
||||
|
||||
def walk_tree(element, depth=0):
|
||||
if depth > 100:
|
||||
return
|
||||
try:
|
||||
if hasattr(element, 'get_object'):
|
||||
element = element.get_object()
|
||||
if isinstance(element, dict):
|
||||
tag = str(element.get("/S", ""))
|
||||
if tag in ["/H1", "/H2", "/H3", "/H4", "/H5", "/H6"]:
|
||||
headings.append(int(tag[2]))
|
||||
mapped_tag = role_map.get(tag, tag)
|
||||
if mapped_tag in HEADING_TAGS:
|
||||
headings.append(int(mapped_tag[2]))
|
||||
kids = element.get("/K", [])
|
||||
if isinstance(kids, list):
|
||||
for kid in kids:
|
||||
walk_tree(kid)
|
||||
walk_tree(kid, depth + 1)
|
||||
elif kids:
|
||||
walk_tree(kids)
|
||||
walk_tree(kids, depth + 1)
|
||||
except (AttributeError, TypeError, KeyError):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ function displayScoreBreakdown(breakdown) {
|
|||
}
|
||||
|
||||
// Maps H-type Matterhorn checkpoint IDs to the Score Breakdown check names that drive them
|
||||
const CP_TO_CHECK = { '04': 'Color Contrast', '13': 'Image Accessibility' };
|
||||
const CP_TO_CHECK = { '04': 'Color Contrast', '13': 'Image Accessibility', '14': 'Heading Structure' };
|
||||
|
||||
function displayMatterhorn(summary) {
|
||||
const card = document.getElementById('matterhornCard');
|
||||
|
|
@ -459,9 +459,9 @@ function displayMatterhorn(summary) {
|
|||
const cpMap = {};
|
||||
summary.checkpoints.forEach(cp => { cpMap[cp.id] = cp; });
|
||||
|
||||
// Compute effective status: H-type FAIL → MANUAL_PASS if linked check is overridden
|
||||
// Compute effective status: FAIL → MANUAL_PASS if linked check is overridden
|
||||
function effectiveStatus(cp) {
|
||||
if (cp.how === 'H' && cp.status === 'FAIL') {
|
||||
if (cp.status === 'FAIL') {
|
||||
const linked = CP_TO_CHECK[cp.id];
|
||||
if (linked && overriddenChecks.has(linked)) return 'MANUAL_PASS';
|
||||
}
|
||||
|
|
@ -503,7 +503,7 @@ function displayMatterhorn(summary) {
|
|||
<button class="btn-unoverride" onclick="unoverrideCheck('${escapeAttr(linked)}')">↩ Undo</button>`;
|
||||
} else if (effStatus === 'PASS') {
|
||||
statusHtml = `<span class="mh-pass">✓ PASS</span>`;
|
||||
} else if (effStatus === 'FAIL' && cp.how === 'H' && CP_TO_CHECK[cp.id]) {
|
||||
} else if (effStatus === 'FAIL' && CP_TO_CHECK[cp.id]) {
|
||||
const linked = CP_TO_CHECK[cp.id];
|
||||
statusHtml = `<span class="mh-fail">✗ FAIL</span>
|
||||
<button class="btn-mark-passed" onclick="overrideCheck('${escapeAttr(linked)}')">✓ Mark as Passed</button>`;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue