Changeset 3453804
- Timestamp:
- 02/04/2026 12:59:39 PM (8 weeks ago)
- Location:
- 3task-glossary/trunk
- Files:
-
- 5 edited
-
3task-glossary.php (modified) (4 diffs)
-
includes/class-admin.php (modified) (4 diffs)
-
includes/class-frontend.php (modified) (5 diffs)
-
includes/class-options.php (modified) (2 diffs)
-
readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
3task-glossary/trunk/3task-glossary.php
r3447608 r3453804 4 4 * Plugin URI: https://wordpress.org/plugins/3task-glossary/ 5 5 * Description: Create glossaries, dictionaries & knowledge bases using WordPress pages. A-Z navigation, auto-linking, dark mode. No database, just pages. 6 * Version: 2. 1.06 * Version: 2.2.0 7 7 * Requires at least: 5.8 8 8 * Requires PHP: 7.4 … … 15 15 * 16 16 * @package 3Task_Glossary 17 * @version 2. 1.017 * @version 2.2.0 18 18 */ 19 19 … … 23 23 } 24 24 25 // Plugin constants. 26 define( 'AZGL_VERSION', '2.1.0' ); 27 define( 'AZGL_PLUGIN_FILE', __FILE__ ); 28 define( 'AZGL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 29 define( 'AZGL_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 30 define( 'AZGL_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); 31 32 // Limits for Lite version. 33 // Removed limits for WordPress.org compliance - fully functional lite version 34 define( 'AZGL_MAX_GLOSSARIES', 999 ); // No functional limits 35 define( 'AZGL_MAX_ENTRIES', 999999 ); // No functional limits 36 define( 'AZGL_SUPPORTER_MAX_GLOSSARIES', 999 ); 37 define( 'AZGL_SUPPORTER_MAX_ENTRIES', 999999 ); 25 // Prevent conflict with old simple-seo-glossary plugin. 26 // Check for the specific old plugin file, not just the class name. 27 if ( defined( 'AZGL_PLUGIN_FILE' ) && strpos( AZGL_PLUGIN_FILE, '3task-glossary' ) === false ) { 28 add_action( 'admin_notices', function() { 29 echo '<div class="notice notice-error"><p><strong>3task Glossary:</strong> '; 30 echo esc_html__( 'Please deactivate the old "Simple SEO Glossary" plugin. Both plugins cannot run simultaneously.', '3task-glossary' ); 31 echo '</p></div>'; 32 } ); 33 return; 34 } 35 36 // Plugin constants (with defined checks for safety). 37 if ( ! defined( 'AZGL_VERSION' ) ) { 38 define( 'AZGL_VERSION', '2.2.0' ); 39 } 40 if ( ! defined( 'AZGL_PLUGIN_FILE' ) ) { 41 define( 'AZGL_PLUGIN_FILE', __FILE__ ); 42 } 43 if ( ! defined( 'AZGL_PLUGIN_DIR' ) ) { 44 define( 'AZGL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 45 } 46 if ( ! defined( 'AZGL_PLUGIN_URL' ) ) { 47 define( 'AZGL_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 48 } 49 if ( ! defined( 'AZGL_PLUGIN_BASENAME' ) ) { 50 define( 'AZGL_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); 51 } 52 53 // Limits for Lite version (no functional limits for WordPress.org compliance). 54 if ( ! defined( 'AZGL_MAX_GLOSSARIES' ) ) { 55 define( 'AZGL_MAX_GLOSSARIES', 999 ); 56 } 57 if ( ! defined( 'AZGL_MAX_ENTRIES' ) ) { 58 define( 'AZGL_MAX_ENTRIES', 999999 ); 59 } 60 if ( ! defined( 'AZGL_SUPPORTER_MAX_GLOSSARIES' ) ) { 61 define( 'AZGL_SUPPORTER_MAX_GLOSSARIES', 999 ); 62 } 63 if ( ! defined( 'AZGL_SUPPORTER_MAX_ENTRIES' ) ) { 64 define( 'AZGL_SUPPORTER_MAX_ENTRIES', 999999 ); 65 } 38 66 39 67 /** … … 365 393 * @return AZ_Glossary_Lite 366 394 */ 367 function azgl() { 368 return AZ_Glossary_Lite::get_instance(); 395 if ( ! function_exists( 'azgl' ) ) { 396 function azgl() { 397 return AZ_Glossary_Lite::get_instance(); 398 } 369 399 } 370 400 -
3task-glossary/trunk/includes/class-admin.php
r3447608 r3453804 258 258 $settings = array( 259 259 'nav_style' => isset( $_POST['nav_style'] ) ? sanitize_key( wp_unslash( $_POST['nav_style'] ) ) : 'buttons', 260 'inactive_letters' => isset( $_POST['inactive_letters'] ) ,260 'inactive_letters' => isset( $_POST['inactive_letters'] ) ? sanitize_key( wp_unslash( $_POST['inactive_letters'] ) ) : 'accessible', 261 261 'color_scheme' => isset( $_POST['color_scheme'] ) ? sanitize_key( wp_unslash( $_POST['color_scheme'] ) ) : 'emerald', 262 262 'dark_mode' => isset( $_POST['dark_mode'] ) ? sanitize_key( wp_unslash( $_POST['dark_mode'] ) ) : 'auto', … … 268 268 if ( ! in_array( $settings['nav_style'], $valid_styles, true ) ) { 269 269 $settings['nav_style'] = 'buttons'; 270 } 271 272 // Validate inactive_letters. 273 $valid_inactive = array_keys( $this->options->get_inactive_letter_modes() ); 274 if ( ! in_array( $settings['inactive_letters'], $valid_inactive, true ) ) { 275 $settings['inactive_letters'] = 'accessible'; 270 276 } 271 277 … … 718 724 private function render_design_tab() { 719 725 $nav_style = $this->options->get( 'nav_style', 'buttons' ); 720 $inactive_letters = $this->options->get( 'inactive_letters', true);726 $inactive_letters = $this->options->get( 'inactive_letters', 'accessible' ); 721 727 $color_scheme = $this->options->get( 'color_scheme', 'emerald' ); 722 728 $dark_mode = $this->options->get( 'dark_mode', 'auto' ); 723 729 724 $nav_styles = $this->options->get_nav_styles(); 725 $color_schemes = $this->options->get_color_schemes(); 726 $dark_modes = $this->options->get_dark_mode_options(); 730 // Migrate old boolean value to new string format. 731 if ( true === $inactive_letters || '1' === $inactive_letters ) { 732 $inactive_letters = 'show'; 733 } elseif ( false === $inactive_letters || '' === $inactive_letters ) { 734 $inactive_letters = 'none'; 735 } 736 737 $nav_styles = $this->options->get_nav_styles(); 738 $inactive_modes = $this->options->get_inactive_letter_modes(); 739 $color_schemes = $this->options->get_color_schemes(); 740 $dark_modes = $this->options->get_dark_mode_options(); 727 741 ?> 728 742 <div class="azgl-card"> … … 753 767 <tr> 754 768 <th scope="row"> 755 < ?php esc_html_e( 'Inactive Letters', '3task-glossary' ); ?>769 <label for="inactive_letters"><?php esc_html_e( 'Inactive Letters', '3task-glossary' ); ?></label> 756 770 </th> 757 771 <td> 758 <label> 759 <input type="checkbox" name="inactive_letters" value="1" <?php checked( $inactive_letters ); ?>> 760 <?php esc_html_e( 'Show letters without entries (greyed out)', '3task-glossary' ); ?> 761 </label> 772 <select name="inactive_letters" id="inactive_letters"> 773 <?php foreach ( $inactive_modes as $value => $mode ) : ?> 774 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $inactive_letters, $value ); ?>> 775 <?php echo esc_html( $mode['label'] ); ?> 776 </option> 777 <?php endforeach; ?> 778 </select> 779 <p class="description"> 780 <?php 781 $current_mode = isset( $inactive_modes[ $inactive_letters ] ) ? $inactive_modes[ $inactive_letters ] : $inactive_modes['accessible']; 782 echo esc_html( $current_mode['description'] ); 783 ?> 784 </p> 785 <p class="description" style="margin-top:8px;color:#666;"> 786 <span class="dashicons dashicons-universal-access" style="font-size:14px;"></span> 787 <?php esc_html_e( 'Accessibility: "Accessible" mode is recommended for screen reader compatibility.', '3task-glossary' ); ?> 788 </p> 762 789 </td> 763 790 </tr> -
3task-glossary/trunk/includes/class-frontend.php
r3447608 r3453804 137 137 $alphabetic_list = $this->get_alphabetic_list( $entries ); 138 138 $nav_style = $this->options->get( 'nav_style', 'buttons' ); 139 $ show_inactive = $this->options->get( 'inactive_letters', true);139 $inactive_mode = $this->options->get( 'inactive_letters', 'accessible' ); 140 140 $color_scheme = $this->options->get( 'color_scheme', 'emerald' ); 141 142 // Migrate old boolean values. 143 if ( true === $inactive_mode || '1' === $inactive_mode ) { 144 $inactive_mode = 'show'; 145 } elseif ( false === $inactive_mode || '' === $inactive_mode ) { 146 $inactive_mode = 'none'; 147 } 141 148 142 149 $output = ''; … … 144 151 // A-Z Navigation. 145 152 if ( ! empty( $glossary['navigation'] ) ) { 146 $output .= $this->render_navigation( $alphabetic_list, $nav_style, $color_scheme, $ show_inactive );153 $output .= $this->render_navigation( $alphabetic_list, $nav_style, $color_scheme, $inactive_mode ); 147 154 } 148 155 … … 207 214 * @param string $nav_style Navigation style. 208 215 * @param string $color_scheme Color scheme. 209 * @param bool $show_inactive Show inactive letters.216 * @param string $inactive_mode Inactive letters display mode (accessible, hidden, show, none). 210 217 * @return string HTML. 211 218 */ 212 private function render_navigation( $alphabetic_list, $nav_style, $color_scheme, $ show_inactive ) {219 private function render_navigation( $alphabetic_list, $nav_style, $color_scheme, $inactive_mode ) { 213 220 $output = '<nav class="azgl-nav azgl-nav-' . esc_attr( $nav_style ) . ' azgl-scheme-' . esc_attr( $color_scheme ) . '" '; 214 221 $output .= 'role="navigation" aria-label="' . esc_attr__( 'Alphabetical navigation', '3task-glossary' ) . '">'; … … 216 223 foreach ( $alphabetic_list as $letter => $entries ) { 217 224 if ( ! empty( $entries ) ) { 225 // Active letter - always a link. 218 226 $output .= '<a href="#azgl-' . esc_attr( strtolower( $letter ) ) . '" class="azgl-nav-letter">'; 219 227 $output .= esc_html( $letter ); 220 228 $output .= '</a>'; 221 } elseif ( $show_inactive ) { 222 $output .= '<span class="azgl-nav-letter azgl-nav-inactive">' . esc_html( $letter ) . '</span>'; 229 } else { 230 // Inactive letter - render based on accessibility mode. 231 $output .= $this->render_inactive_letter( $letter, $inactive_mode ); 223 232 } 224 233 } … … 227 236 228 237 return $output; 238 } 239 240 /** 241 * Render an inactive letter based on accessibility mode. 242 * 243 * @param string $letter The letter to render. 244 * @param string $inactive_mode Display mode (accessible, hidden, show, none). 245 * @return string HTML. 246 */ 247 private function render_inactive_letter( $letter, $inactive_mode ) { 248 switch ( $inactive_mode ) { 249 case 'accessible': 250 // Screen reader announces "X, no entries" - best for accessibility. 251 return '<span class="azgl-nav-letter azgl-nav-inactive" aria-label="' . 252 /* translators: %s: Letter that has no glossary entries */ 253 esc_attr( sprintf( __( '%s, no entries', '3task-glossary' ), $letter ) ) . 254 '" role="text">' . esc_html( $letter ) . '</span>'; 255 256 case 'hidden': 257 // Visible but hidden from screen readers. 258 return '<span class="azgl-nav-letter azgl-nav-inactive" aria-hidden="true">' . 259 esc_html( $letter ) . '</span>'; 260 261 case 'show': 262 // Legacy mode - visual only, may cause accessibility issues. 263 return '<span class="azgl-nav-letter azgl-nav-inactive">' . 264 esc_html( $letter ) . '</span>'; 265 266 case 'none': 267 default: 268 // Don't render inactive letters at all. 269 return ''; 270 } 229 271 } 230 272 -
3task-glossary/trunk/includes/class-options.php
r3447608 r3453804 51 51 // Display settings. 52 52 'nav_style' => 'buttons', // buttons, pills, minimal. 53 'inactive_letters' => true,53 'inactive_letters' => 'accessible', // show, accessible, hidden, none. 54 54 'color_scheme' => 'emerald', // emerald, ocean, sunset, berry, slate, auto. 55 55 'dark_mode' => 'auto', // auto, light, dark. … … 367 367 368 368 /** 369 * Get available inactive letter display modes. 370 * 371 * Accessibility options for how to handle letters without entries. 372 * 373 * @return array Inactive letter modes with labels and descriptions. 374 */ 375 public function get_inactive_letter_modes() { 376 return array( 377 'accessible' => array( 378 'label' => __( 'Accessible (Recommended)', '3task-glossary' ), 379 'description' => __( 'Screen readers announce "X, no entries"', '3task-glossary' ), 380 ), 381 'hidden' => array( 382 'label' => __( 'Hidden for Screen Readers', '3task-glossary' ), 383 'description' => __( 'Visible but ignored by screen readers', '3task-glossary' ), 384 ), 385 'show' => array( 386 'label' => __( 'Show (Visual Only)', '3task-glossary' ), 387 'description' => __( 'May cause accessibility issues', '3task-glossary' ), 388 ), 389 'none' => array( 390 'label' => __( 'Hide Completely', '3task-glossary' ), 391 'description' => __( 'Only show letters with entries', '3task-glossary' ), 392 ), 393 ); 394 } 395 396 /** 369 397 * Get available linking modes. 370 398 * -
3task-glossary/trunk/readme.txt
r3447608 r3453804 4 4 Requires at least: 5.8 5 5 Tested up to: 6.9 6 Stable tag: 2. 1.06 Stable tag: 2.2.0 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 128 128 129 129 == Changelog == 130 131 = 2.2.0 = 132 * New: Accessibility options for inactive letters (screen reader support) 133 * New: Four display modes for letters without entries: Accessible (with aria-label), Hidden (aria-hidden), Show (visual only), None (hide completely) 134 * Improved: Screen readers now properly announce "X, no entries" instead of reading letters as one string 135 * Thanks to Elena Brescacin for reporting the accessibility issue and contributing the Italian translation 130 136 131 137 = 2.1.0 = … … 151 157 == Upgrade Notice == 152 158 159 = 2.2.0 = 160 Accessibility improvement: Inactive letters now work properly with screen readers. Choose from 4 display modes in Design settings. 161 153 162 = 2.1.0 = 154 163 Plugin renamed to 3task Glossary. Now optimized for glossaries, dictionaries, wikis and knowledge bases.
Note: See TracChangeset
for help on using the changeset viewer.