feat: RCT inline abbreviation tooltip on verdict legend strip (v2.2.1) (#53)

CI green (PHP Lint 8.1/8.2/8.3 ✓, PHPCS ✓, PHPUnit 8.1/8.2/8.3 ✓). QA: PASS.
This commit is contained in:
peptiderepo
2026-04-29 13:29:04 +07:00
committed by GitHub
parent bdc3ace6cf
commit 2b23bb7e2a
7 changed files with 267 additions and 5 deletions

View File

@@ -19,7 +19,7 @@
*
* Canonical order matches CMO brief §5.1 and the 5-state enum in verdict-meta.php.
*
* @return array[] Each element: state (string), glyph (string), label (string), description (string).
* @return array[] Each element: state (string), glyph (string), label (string), description (string), abbrs (array, optional).
*/
function peptide_starter_get_verdict_taxonomy() {
return array(
@@ -28,6 +28,10 @@ function peptide_starter_get_verdict_taxonomy() {
'glyph' => '✓',
'label' => 'Established',
'description' => 'Strong RCT evidence; widely prescribed or validated.',
// abbrs: terms in description that should render as inline tap-targets.
'abbrs' => array(
'RCT' => 'Randomized Controlled Trial — the gold standard for clinical evidence. Participants are randomly assigned to treatment or control groups to measure real effect.',
),
),
array(
'state' => 'promising',
@@ -88,3 +92,46 @@ function peptide_starter_get_verdict_config() {
),
);
}
/**
* Renders a description string with optional inline abbreviation tap-targets.
*
* What: Builds safe HTML for a verdict card description, replacing known
* abbreviation terms with <abbr> elements that trigger a tooltip.
* Who calls it: front-page.php verdict explainer loop.
* Depends on: Nothing — pure string transformation.
*
* The output is intentionally built from escaped components (not from raw $text)
* so we never expose unescaped user or data-layer content. Each substitution is:
* esc_html( $text ) → str_replace( literal_term, safe_abbr_html )
* This is safe because the abbr tag, class, and data-def are all hardcoded or
* escaped here, and the term key is a literal constant from our own data array.
*
* @param string $text Plain-text description string. Will be HTML-escaped.
* @param array $abbrs Associative array of term => definition. Keys are literal
* strings (e.g. 'RCT'). Values are plain-text definitions.
* @return string Safe HTML string suitable for echo without further escaping.
*
* @see inc/verdict-helpers.php — $abbrs data lives in peptide_starter_get_verdict_taxonomy()
* @see assets/js/abbr-tooltip.js — JS that handles tap/click to show the popover
* @see style.css — .pr-abbr and .pr-abbr-popover styles
*/
function peptide_starter_render_desc( string $text, array $abbrs ): string {
$html = esc_html( $text );
foreach ( $abbrs as $term => $definition ) {
$safe_term = esc_html( $term );
$safe_def = esc_attr( $definition );
$abbr_html = sprintf(
'<abbr class="pr-abbr" data-def="%s" tabindex="0" role="button" aria-label="%s: %s">%s</abbr>',
$safe_def,
$safe_term,
$safe_def,
$safe_term
);
// Replace only the first occurrence — abbreviations should not stack.
$html = preg_replace( '/' . preg_quote( $safe_term, '/' ) . '/', $abbr_html, $html, 1 );
}
return $html;
}