Plugin Directory

Changeset 3498697


Ignore:
Timestamp:
04/04/2026 10:48:55 AM (31 hours ago)
Author:
s7ntech
Message:

v2.1.0: Mode field, replace behavior with related posts, minimal comma fix, UI cleanup

Location:
tag-display/trunk
Files:
1 added
22 edited

Legend:

Unmodified
Added
Removed
  • tag-display/trunk/admin/css/tag-display-admin.css

    r3493065 r3498697  
    11/**
    2  * Tag Display Admin CSS
     2 * Tag Display - Admin CSS
    33 * Modern redesign for WordPress admin panel
    44 */
     
    149149
    150150/* =============================================
    151    FORM TABLE (Settings API) Modern override
     151   FORM TABLE (Settings API) - Modern override
    152152   ============================================= */
    153153
     
    262262}
    263263
    264 /* Old shortcode-info class keep for compatibility */
     264/* Old shortcode-info class - keep for compatibility */
    265265.shortcode-info {
    266266    background: #f6f7f7;
  • tag-display/trunk/admin/js/tag-display-admin.js

    r3477469 r3498697  
    2929        updateTemplatePreview();
    3030
    31         // T11 Restore active tab from localStorage
     31        // T11 - Restore active tab from localStorage
    3232        var savedTab = localStorage.getItem('s7n_tag_display_active_tab');
    3333        if (savedTab && $(savedTab).length) {
     
    5656            $(target).addClass('active');
    5757
    58             // T11 Persist active tab
     58            // T11 - Persist active tab
    5959            localStorage.setItem('s7n_tag_display_active_tab', target);
    6060        });
    6161
    62         // T13 Live template preview: switch to preview tab and highlight matching card
     62        // T13 - Live template preview: switch to preview tab and highlight matching card
    6363        $('#s7n_tag_display_template').on('change', function() {
    6464            var selectedTemplate = $(this).val();
     
    7777        });
    7878
    79         // T10 Reset colors to defaults
     79        // T10 - Reset colors to defaults
    8080        var colorDefaults = {
    8181            's7n_tag_display_bg_color':         '#f1f1f1',
     
    9595        });
    9696
    97         // T12 — Dirty state: show unsaved-changes notice on any form field change
     97        // Smart Visibility: show/hide fields based on Mode and Behavior selection
     98        function updateSmartVisibilityFields() {
     99            var mode     = $('#s7n_tag_display_smart_mode').val();
     100            var behavior = $('#s7n_tag_display_smart_behavior').val();
     101
     102            // Density threshold row: only relevant when Mode = Density (or legacy Default)
     103            var $densityRow = $('#s7n_tag_display_smart_density_threshold').closest('tr');
     104            if ( mode === 'density' || mode === '' ) {
     105                $densityRow.show();
     106            } else {
     107                $densityRow.hide();
     108            }
     109
     110            // Related Topics Title row: only relevant when Behavior = Replace
     111            var $relatedRow = $('#s7n_tag_display_related_title').closest('tr');
     112            if ( behavior === 'replace' ) {
     113                $relatedRow.show();
     114            } else {
     115                $relatedRow.hide();
     116            }
     117
     118            // Enable toggle: show override note when Mode is not Default
     119            var $overrideNote = $('.s7n-mode-override-note');
     120            if ( mode !== '' ) {
     121                $overrideNote.show();
     122            } else {
     123                $overrideNote.hide();
     124            }
     125        }
     126
     127        if ( $('#s7n_tag_display_smart_mode').length ) {
     128            $('#s7n_tag_display_smart_mode').on('change', updateSmartVisibilityFields);
     129            $('#s7n_tag_display_smart_behavior').on('change', updateSmartVisibilityFields);
     130            updateSmartVisibilityFields();
     131        }
     132
     133        // T12 - Dirty state: show unsaved-changes notice on any form field change
    98134        $('form').on('change input', ':input:not([type="submit"])', function() {
    99135            markDirty();
  • tag-display/trunk/admin/partials/tag-display-admin-display.php

    r3498672 r3498697  
    121121                    <p><code>[s7n_tag_display smart="true" min="3" behavior="collapse"]</code></p>
    122122                    <dl class="shortcode-attrs">
    123                         <dt><code>smart</code></dt><dd><?php esc_html_e( 'true / false override the global toggle', 'tag-display' ); ?></dd>
     123                        <dt><code>smart</code></dt><dd><?php esc_html_e( 'true / false - override the global toggle', 'tag-display' ); ?></dd>
    124124                        <dt><code>min</code></dt><dd><?php esc_html_e( 'minimum tag count threshold for this instance', 'tag-display' ); ?></dd>
    125125                        <dt><code>behavior</code></dt><dd>hide, collapse, seo</dd>
     
    192192                        </div>
    193193                        <div class="template-preview-body">
    194                             <p class="template-preview-desc"><?php esc_html_e( 'Tags sized proportionally to post count more posts, bigger tag.', 'tag-display' ); ?></p>
     194                            <p class="template-preview-desc"><?php esc_html_e( 'Tags sized proportionally to post count - more posts, bigger tag.', 'tag-display' ); ?></p>
    195195                            <div class="preview-container">
    196196                                <div class="preview-title"><?php esc_html_e( 'Tags:', 'tag-display' ); ?></div>
     
    233233                        </div>
    234234                        <div class="template-preview-body">
    235                             <p class="template-preview-desc"><?php esc_html_e( 'Transparent background with a colored border modern pill-style.', 'tag-display' ); ?></p>
     235                            <p class="template-preview-desc"><?php esc_html_e( 'Transparent background with a colored border - modern pill-style.', 'tag-display' ); ?></p>
    236236                            <div class="preview-container">
    237237                                <div class="preview-title"><?php esc_html_e( 'Tags:', 'tag-display' ); ?></div>
     
    257257                        </div>
    258258                        <div class="template-preview-body">
    259                             <p class="template-preview-desc"><?php esc_html_e( 'Social-style tags prefixed with # no border, no background.', 'tag-display' ); ?></p>
     259                            <p class="template-preview-desc"><?php esc_html_e( 'Social-style tags prefixed with # - no border, no background.', 'tag-display' ); ?></p>
    260260                            <div class="preview-container">
    261261                                <div class="preview-title"><?php esc_html_e( 'Tags:', 'tag-display' ); ?></div>
     
    288288                        <p><?php esc_html_e( 'Display tags in one of three ways:', 'tag-display' ); ?></p>
    289289                        <ol>
    290                             <li><strong><?php esc_html_e( 'Shortcode', 'tag-display' ); ?></strong> <?php esc_html_e( 'paste', 'tag-display' ); ?> <code>[s7n_tag_display]</code> <?php esc_html_e( 'in any post or page.', 'tag-display' ); ?></li>
    291                             <li><strong><?php esc_html_e( 'Gutenberg block', 'tag-display' ); ?></strong> <?php esc_html_e( 'search "Tag Display" in the block inserter.', 'tag-display' ); ?></li>
    292                             <li><strong><?php esc_html_e( 'Automatic', 'tag-display' ); ?></strong> <?php esc_html_e( 'enable in Content Types tab to add tags to every post automatically.', 'tag-display' ); ?></li>
     290                            <li><strong><?php esc_html_e( 'Shortcode', 'tag-display' ); ?></strong> - <?php esc_html_e( 'paste', 'tag-display' ); ?> <code>[s7n_tag_display]</code> <?php esc_html_e( 'in any post or page.', 'tag-display' ); ?></li>
     291                            <li><strong><?php esc_html_e( 'Gutenberg block', 'tag-display' ); ?></strong> - <?php esc_html_e( 'search "Tag Display" in the block inserter.', 'tag-display' ); ?></li>
     292                            <li><strong><?php esc_html_e( 'Automatic', 'tag-display' ); ?></strong> - <?php esc_html_e( 'enable in Content Types tab to add tags to every post automatically.', 'tag-display' ); ?></li>
    293293                        </ol>
    294294                    </div>
     
    297297                        <h3><?php esc_html_e( 'Templates', 'tag-display' ); ?></h3>
    298298                        <ul>
    299                             <li><strong><?php esc_html_e( 'Default', 'tag-display' ); ?></strong> <?php esc_html_e( 'button-style tags with hover effects.', 'tag-display' ); ?></li>
    300                             <li><strong><?php esc_html_e( 'Minimal', 'tag-display' ); ?></strong> <?php esc_html_e( 'simple comma-separated text links.', 'tag-display' ); ?></li>
    301                             <li><strong><?php esc_html_e( 'Tag Cloud', 'tag-display' ); ?></strong> <?php esc_html_e( 'tags sized proportionally to post count.', 'tag-display' ); ?></li>
    302                             <li><strong><?php esc_html_e( 'Outlined', 'tag-display' ); ?></strong> <?php esc_html_e( 'transparent background with colored pill border.', 'tag-display' ); ?></li>
    303                             <li><strong><?php esc_html_e( 'Hashtag', 'tag-display' ); ?></strong> <?php esc_html_e( 'social-style #tag format.', 'tag-display' ); ?></li>
     299                            <li><strong><?php esc_html_e( 'Default', 'tag-display' ); ?></strong> - <?php esc_html_e( 'button-style tags with hover effects.', 'tag-display' ); ?></li>
     300                            <li><strong><?php esc_html_e( 'Minimal', 'tag-display' ); ?></strong> - <?php esc_html_e( 'simple comma-separated text links.', 'tag-display' ); ?></li>
     301                            <li><strong><?php esc_html_e( 'Tag Cloud', 'tag-display' ); ?></strong> - <?php esc_html_e( 'tags sized proportionally to post count.', 'tag-display' ); ?></li>
     302                            <li><strong><?php esc_html_e( 'Outlined', 'tag-display' ); ?></strong> - <?php esc_html_e( 'transparent background with colored pill border.', 'tag-display' ); ?></li>
     303                            <li><strong><?php esc_html_e( 'Hashtag', 'tag-display' ); ?></strong> - <?php esc_html_e( 'social-style #tag format.', 'tag-display' ); ?></li>
    304304                        </ul>
    305305                        <p><?php esc_html_e( 'Use the Template Preview tab to compare them with your current colors.', 'tag-display' ); ?></p>
     
    338338                        <p><?php esc_html_e( 'A fully commented starter file is included in the plugin\'s', 'tag-display' ); ?> <code>examples/</code> <?php esc_html_e( 'folder. Available variables in your template:', 'tag-display' ); ?></p>
    339339                        <ul>
    340                             <li><code>$tags</code> <?php esc_html_e( 'array of WP_Term objects (→name, →slug, →count)', 'tag-display' ); ?></li>
     340                            <li><code>$tags</code> - <?php esc_html_e( 'array of WP_Term objects (→name, →slug, →count)', 'tag-display' ); ?></li>
    341341                            <li><code>$display_title</code>, <code>$display_nofollow</code>, <code>$display_new_tab</code>, <code>$display_show_count</code></li>
    342342                        </ul>
  • tag-display/trunk/block/edit.js

    r3477469 r3498697  
    2727    const templateOptions = [
    2828        { label: __( 'Default (from settings)', 'tag-display' ), value: '' },
    29         { label: __( 'Default Buttons', 'tag-display' ), value: 'default' },
    30         { label: __( 'Minimal Text links', 'tag-display' ), value: 'minimal' },
    31         { label: __( 'Cloud Tag cloud', 'tag-display' ), value: 'cloud' },
    32         { label: __( 'Outlined Border style', 'tag-display' ), value: 'outlined' },
    33         { label: __( 'Hashtag Social style', 'tag-display' ), value: 'hashtag' },
     29        { label: __( 'Default - Buttons', 'tag-display' ), value: 'default' },
     30        { label: __( 'Minimal - Text links', 'tag-display' ), value: 'minimal' },
     31        { label: __( 'Cloud - Tag cloud', 'tag-display' ), value: 'cloud' },
     32        { label: __( 'Outlined - Border style', 'tag-display' ), value: 'outlined' },
     33        { label: __( 'Hashtag - Social style', 'tag-display' ), value: 'hashtag' },
    3434    ];
    3535
     
    117117                />
    118118                <strong>{ __( 'Tag Display', 'tag-display' ) }</strong>
    119                 <span style={ { color: '#757575' } }> { templateLabel }</span>
     119                <span style={ { color: '#757575' } }>- { templateLabel }</span>
    120120            </div>
    121121        </>
  • tag-display/trunk/block/index.js

    r3477469 r3498697  
    55registerBlockType( metadata.name, {
    66    edit: Edit,
    7     // Dynamic block render handled by PHP render_callback
     7    // Dynamic block - render handled by PHP render_callback
    88    save: () => null,
    99} );
  • tag-display/trunk/block/render.php

    r3496031 r3498697  
    2020     *
    2121     * @param  array    $attributes  Block attributes.
    22      * @param  string   $content     Inner block content (unused dynamic block).
     22     * @param  string   $content     Inner block content (unused - dynamic block).
    2323     * @param  WP_Block $block       Block instance.
    2424     * @return string                Rendered HTML output.
     
    150150
    151151        // --- Include template ---------------------------------------------------
    152         // T38 Theme override: look for tag-display-template-{name}.php in child/parent theme
     152        // T38 - Theme override: look for tag-display-template-{name}.php in child/parent theme
    153153        $template_filename = 'tag-display-template-' . $template . '.php';
    154154        $theme_template    = locate_template( $template_filename );
  • tag-display/trunk/examples/tag-display-template-custom.php

    r3496031 r3498697  
    1515 *
    1616 * Available variables (set by the plugin before including this file):
    17  *   $tags               (array)    array of WP_Term objects
    18  *   $display_title      (string)  label shown above the tags (e.g. "Tags:")
    19  *   $display_nofollow   (bool)    whether to add rel="nofollow"
    20  *   $display_new_tab    (bool)    whether to open links in a new tab
    21  *   $display_show_count (bool)    whether to show post count next to tag name
     17 *   $tags               (array)   - array of WP_Term objects
     18 *   $display_title      (string)  - label shown above the tags (e.g. "Tags:")
     19 *   $display_nofollow   (bool)    - whether to add rel="nofollow"
     20 *   $display_new_tab    (bool)    - whether to open links in a new tab
     21 *   $display_show_count (bool)    - whether to show post count next to tag name
    2222 *
    2323 * Each $td_tag object has:
    24  *   $td_tag->name    display name (e.g. "WordPress")
    25  *   $td_tag->slug    URL slug (e.g. "my-tag")
    26  *   $td_tag->count  number of posts with this tag
     24 *   $td_tag->name   - display name (e.g. "WordPress")
     25 *   $td_tag->slug   - URL slug (e.g. "my-tag")
     26 *   $td_tag->count  - number of posts with this tag
    2727 *
    2828 * @package Tag_Display
  • tag-display/trunk/includes/class-tag-display-admin.php

    r3498672 r3498697  
    378378        );
    379379
    380         // T14 Tag ordering
     380        // T14 - Tag ordering
    381381        register_setting(
    382382            's7n_tag_display_settings',
     
    389389        );
    390390
    391         // T15 Max tags
     391        // T15 - Max tags
    392392        register_setting(
    393393            's7n_tag_display_settings',
     
    400400        );
    401401
    402         // T16 Exclude tags
     402        // T16 - Exclude tags
    403403        register_setting(
    404404            's7n_tag_display_settings',
     
    411411        );
    412412
    413         // T17 Auto-display position
     413        // T17 - Auto-display position
    414414        register_setting(
    415415            's7n_tag_display_settings',
     
    422422        );
    423423
    424         // T18 nofollow
     424        // T18 - nofollow
    425425        register_setting(
    426426            's7n_tag_display_settings',
     
    433433        );
    434434
    435         // T19 new tab
     435        // T19 - new tab
    436436        register_setting(
    437437            's7n_tag_display_settings',
     
    444444        );
    445445
    446         // T20 show count
     446        // T20 - show count
    447447        register_setting(
    448448            's7n_tag_display_settings',
     
    535535        );
    536536
    537         // T2 Content density options.
     537        // T2 - Content density options.
    538538        register_setting(
    539539            's7n_tag_display_settings',
     
    553553                'sanitize_callback' => array( $this, 'sanitize_density_threshold' ),
    554554                'default'           => 0.005,
     555            )
     556        );
     557
     558        // T7 - Mode option (supersedes smart_enabled + use_density when set).
     559        register_setting(
     560            's7n_tag_display_settings',
     561            's7n_tag_display_smart_mode',
     562            array(
     563                'type'              => 'string',
     564                'sanitize_callback' => array( $this, 'sanitize_smart_mode' ),
     565                'default'           => '',
     566            )
     567        );
     568
     569        // T9 - Related posts title for behavior=replace.
     570        register_setting(
     571            's7n_tag_display_settings',
     572            's7n_tag_display_related_title',
     573            array(
     574                'type'              => 'string',
     575                'sanitize_callback' => 'sanitize_text_field',
     576                'default'           => '',
    555577            )
    556578        );
     
    564586
    565587        add_settings_field(
     588            's7n_tag_display_smart_mode',
     589            __( 'Mode', 'tag-display' ),
     590            array( $this, 's7n_tag_display_smart_mode_callback' ),
     591            's7n_tag_display_settings',
     592            's7n_tag_display_smart_section'
     593        );
     594
     595        add_settings_field(
    566596            's7n_tag_display_smart_enabled',
    567597            __( 'Enable Smart Visibility', 'tag-display' ),
     
    588618
    589619        add_settings_field(
     620            's7n_tag_display_related_title',
     621            __( 'Related Topics Title', 'tag-display' ),
     622            array( $this, 's7n_tag_display_related_title_callback' ),
     623            's7n_tag_display_settings',
     624            's7n_tag_display_smart_section'
     625        );
     626
     627        add_settings_field(
    590628            's7n_tag_display_smart_use_density',
    591             __( 'Content Density Analysis', 'tag-display' ),
     629            __( 'Density Threshold', 'tag-display' ),
    592630            array( $this, 's7n_tag_display_smart_density_callback' ),
    593631            's7n_tag_display_settings',
     
    11121150
    11131151    // =========================================================================
    1114     // Smart Visibility section, fields, sanitize
     1152    // Smart Visibility - section, fields, sanitize
    11151153    // =========================================================================
    11161154
     
    11211159     */
    11221160    public function s7n_tag_display_smart_section_callback() {
    1123         echo '<p>' . esc_html__( 'Automatically adapt tag display based on tag count improving both SEO and user experience.', 'tag-display' ) . '</p>';
     1161        echo '<p>' . esc_html__( 'Automatically adapt tag display based on tag count - improving both SEO and user experience.', 'tag-display' ) . '</p>';
    11241162    }
    11251163
     
    11371175        </label>
    11381176        <p class="description"><?php esc_html_e( 'When enabled, tag display adapts automatically based on the threshold below.', 'tag-display' ); ?></p>
     1177        <p class="description s7n-mode-override-note" style="display:none;color:#b32d2e;margin-top:4px">
     1178            <?php esc_html_e( 'This toggle is overridden by the Mode setting above. Change Mode to "Default" to use this toggle again.', 'tag-display' ); ?>
     1179        </p>
    11391180        <?php
    11401181    }
     
    11621203        $behavior = get_option( 's7n_tag_display_smart_behavior', 'hide' );
    11631204        $options  = array(
    1164             'hide'     => __( 'Hide — suppress tags entirely (no DOM output)', 'tag-display' ),
    1165             'hidden'   => __( 'Hidden — render tags invisibly, togglable via JavaScript', 'tag-display' ),
    1166             'collapse' => __( 'Collapse — show a "Show tags" button to expand', 'tag-display' ),
    1167             'seo'      => __( 'SEO hidden — invisible to visitors, visible to crawlers', 'tag-display' ),
     1205            'hide'     => __( 'Hide - suppress tags entirely (no DOM output)', 'tag-display' ),
     1206            'hidden'   => __( 'Hidden - render tags invisibly, togglable via JavaScript', 'tag-display' ),
     1207            'collapse' => __( 'Collapse - show a "Show tags" button to expand', 'tag-display' ),
     1208            'seo'      => __( 'SEO hidden - invisible to visitors, visible to crawlers', 'tag-display' ),
     1209            'replace'  => __( 'Replace - show related posts instead of tags', 'tag-display' ),
    11681210        );
    11691211        ?>
     
    11831225     *
    11841226     * @since  1.9.0
    1185      * @param  string $input    The behavior value to sanitize.
    1186      * @return string              One of 'hide', 'hidden', 'collapse', 'seo'.
     1227     * @since  2.1.0 Added 'replace'.
     1228     * @param  string $input The behavior value to sanitize.
     1229     * @return string        One of 'hide', 'hidden', 'collapse', 'seo', 'replace'.
    11871230     */
    11881231    public function sanitize_smart_behavior( $input ) {
    1189         $valid = array( 'hide', 'hidden', 'collapse', 'seo' );
     1232        $valid = array( 'hide', 'hidden', 'collapse', 'seo', 'replace' );
    11901233        return in_array( $input, $valid, true ) ? $input : 'hide';
    11911234    }
    11921235
    11931236    /**
     1237     * Render the smart_mode field.
     1238     *
     1239     * @since 2.1.0
     1240     */
     1241    public function s7n_tag_display_smart_mode_callback() {
     1242        $mode    = get_option( 's7n_tag_display_smart_mode', '' );
     1243        $options = array(
     1244            ''         => __( 'Default (use Enable toggle below)', 'tag-display' ),
     1245            'auto'     => __( 'Auto - activate when tag count is below threshold', 'tag-display' ),
     1246            'density'  => __( 'Density - also activate when tag density is low', 'tag-display' ),
     1247            'ux'       => __( 'UX - always activate (behavior decides the response)', 'tag-display' ),
     1248            'disabled' => __( 'Disabled - Smart Visibility is off', 'tag-display' ),
     1249        );
     1250        ?>
     1251        <select name="s7n_tag_display_smart_mode" id="s7n_tag_display_smart_mode">
     1252            <?php foreach ( $options as $value => $label ) : ?>
     1253                <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $mode, $value ); ?>>
     1254                    <?php echo esc_html( $label ); ?>
     1255                </option>
     1256            <?php endforeach; ?>
     1257        </select>
     1258        <p class="description"><?php esc_html_e( 'When set, Mode overrides the Enable toggle. Density mode also uses the density threshold below.', 'tag-display' ); ?></p>
     1259        <?php
     1260    }
     1261
     1262    /**
     1263     * Render the related_title field.
     1264     *
     1265     * @since 2.1.0
     1266     */
     1267    public function s7n_tag_display_related_title_callback() {
     1268        $title = get_option( 's7n_tag_display_related_title', '' );
     1269        ?>
     1270        <input type="text" name="s7n_tag_display_related_title" id="s7n_tag_display_related_title"
     1271            value="<?php echo esc_attr( $title ); ?>" class="regular-text"
     1272            placeholder="<?php esc_attr_e( 'Related Topics', 'tag-display' ); ?>">
     1273        <p class="description"><?php esc_html_e( 'Title shown above related posts when Behavior is set to Replace. Leave empty to use the default.', 'tag-display' ); ?></p>
     1274        <?php
     1275    }
     1276
     1277    /**
     1278     * Sanitize the smart_mode setting.
     1279     *
     1280     * @since  2.1.0
     1281     * @param  string $input The mode value to sanitize.
     1282     * @return string        One of '', 'auto', 'density', 'ux', 'disabled'.
     1283     */
     1284    public function sanitize_smart_mode( $input ) {
     1285        $valid = array( '', 'auto', 'density', 'ux', 'disabled' );
     1286        return in_array( $input, $valid, true ) ? $input : '';
     1287    }
     1288
     1289    /**
    11941290     * Render the content density analysis fields.
    11951291     *
     
    11971293     */
    11981294    public function s7n_tag_display_smart_density_callback() {
    1199         $use_density       = get_option( 's7n_tag_display_smart_use_density', false );
    12001295        $density_threshold = get_option( 's7n_tag_display_smart_density_threshold', 0.005 );
    1201         ?>
    1202         <fieldset>
    1203             <label>
    1204                 <input type="checkbox" name="s7n_tag_display_smart_use_density" id="s7n_tag_display_smart_use_density" value="1" <?php checked( $use_density ); ?>>
    1205                 <?php esc_html_e( 'Also apply smart logic when tag density is low', 'tag-display' ); ?>
    1206             </label>
    1207             <p class="description">
    1208                 <?php esc_html_e( 'Tag density = number of tags ÷ number of words in the post. A low density means few tags relative to the content length.', 'tag-display' ); ?>
    1209             </p>
    1210             <br>
    1211             <label for="s7n_tag_display_smart_density_threshold">
    1212                 <?php esc_html_e( 'Density threshold:', 'tag-display' ); ?>
    1213             </label>
    1214             <input type="number" name="s7n_tag_display_smart_density_threshold" id="s7n_tag_display_smart_density_threshold"
    1215                 value="<?php echo esc_attr( $density_threshold ); ?>" min="0.001" max="1" step="0.001" class="small-text">
    1216             <p class="description">
    1217                 <?php esc_html_e( 'Default: 0.005 (1 tag per 200 words). If density is below this value the selected behavior triggers, even if the tag count meets the threshold.', 'tag-display' ); ?>
    1218             </p>
    1219         </fieldset>
     1296        // Preserve legacy use_density flag via hidden input for backward compatibility.
     1297        $use_density = get_option( 's7n_tag_display_smart_use_density', false );
     1298        ?>
     1299        <input type="hidden" name="s7n_tag_display_smart_use_density" value="<?php echo $use_density ? '1' : '0'; ?>">
     1300        <input type="number" name="s7n_tag_display_smart_density_threshold" id="s7n_tag_display_smart_density_threshold"
     1301            value="<?php echo esc_attr( $density_threshold ); ?>" min="0.001" max="1" step="0.001" class="small-text">
     1302        <p class="description">
     1303            <?php esc_html_e( 'Active when Mode is set to "Density". Minimum ratio of tags to words: below this value the selected behavior triggers.', 'tag-display' ); ?>
     1304            <?php esc_html_e( 'Default: 0.005 (1 tag per 200 words). Lower values are stricter.', 'tag-display' ); ?>
     1305        </p>
    12201306        <?php
    12211307    }
  • tag-display/trunk/includes/class-tag-display-public.php

    r3496031 r3498697  
    125125     */
    126126    public function s7n_tag_display_shortcode( $atts ) {
    127         // T25 Extended shortcode attributes with global option defaults
     127        // T25 - Extended shortcode attributes with global option defaults
    128128        $atts = shortcode_atts(
    129129            array(
     
    196196                $tag_html = $this->get_tag_display( $template );
    197197
    198                 // T22 Position before or after content
     198                // T22 - Position before or after content
    199199                $position = get_option( 's7n_tag_display_position', 'after' );
    200200                if ( 'before' === $position ) {
     
    238238        }
    239239
    240         // T21 Exclude tags by slug
     240        // T21 - Exclude tags by slug
    241241        $exclude_raw = isset( $args['exclude'] ) ? $args['exclude'] : get_option( 's7n_tag_display_exclude_tags', '' );
    242242        if ( ! empty( $exclude_raw ) ) {
     
    254254        }
    255255
    256         // T21 Order tags
     256        // T21 - Order tags
    257257        $order = isset( $args['order'] ) ? $args['order'] : get_option( 's7n_tag_display_order', 'none' );
    258258        switch ( $order ) {
     
    294294        }
    295295
    296         // T21 Limit number of tags
     296        // T21 - Limit number of tags
    297297        $max = isset( $args['max'] ) ? (int) $args['max'] : (int) get_option( 's7n_tag_display_max_tags', 0 );
    298298        if ( $max > 0 && count( $all_terms ) > $max ) {
     
    347347        );
    348348
    349         // T23 Link attributes exposed to templates
     349        // T23 - Link attributes exposed to templates
    350350        $display_nofollow = ! empty( $args['nofollow'] ) ? (bool) $args['nofollow']
    351351                            : (bool) get_option( 's7n_tag_display_link_nofollow', false );
     
    353353                            : (bool) get_option( 's7n_tag_display_link_new_tab', false );
    354354
    355         // T24 Show count exposed to templates
     355        // T24 - Show count exposed to templates
    356356        $display_show_count = ! empty( $args['show_count'] ) ? (bool) $args['show_count']
    357357                                : (bool) get_option( 's7n_tag_display_show_count', false );
    358358
    359         // T25 Title override for shortcode
     359        // T25 - Title override for shortcode
    360360        if ( isset( $args['title'] ) && '' !== $args['title'] ) {
    361361            $display_title = sanitize_text_field( $args['title'] );
     
    367367        ob_start();
    368368
    369         // T38 Theme template override: look for tag-display-template-{name}.php in child/parent theme
     369        // T38 - Theme template override: look for tag-display-template-{name}.php in child/parent theme
    370370        $template_filename = 'tag-display-template-' . $template . '.php';
    371371        $theme_template    = locate_template( $template_filename );
    372372
    373373        if ( $theme_template && validate_file( $theme_template ) === 0 ) {
    374             // Theme override found and path is safe use it
     374            // Theme override found and path is safe - use it
    375375            include $theme_template;
    376376        } else {
  • tag-display/trunk/includes/class-tag-display-smart-visibility.php

    r3498672 r3498697  
    4343        add_filter( 's7n_tag_display_tags', array( $this, 'filter_tags' ), 10, 3 );
    4444        add_filter( 's7n_tag_display_output', array( $this, 'filter_output' ), 10, 4 );
     45        // T10 - Invalidate related posts cache when post terms change.
     46        add_action( 'set_object_terms', array( $this, 'invalidate_related_cache' ), 10, 1 );
    4547    }
    4648
     
    7072        }
    7173
    72         // T1 Calculate content density and store in a shared static cache
     74        // T1 - Calculate content density and store in a shared static cache
    7375        // keyed by post_id so filter_output can read it without another get_post().
    7476        $this->prime_density_cache( $post_id );
     
    125127        }
    126128
    127         // T4 'hidden': DOM present, visually hidden, togglable via JS.
     129        // T4 - 'hidden': DOM present, visually hidden, togglable via JS.
    128130        if ( 'hidden' === $behavior ) {
    129131            return '<div class="s7n-tags--hidden" aria-hidden="true">' . $output . '</div>';
     132        }
     133
     134        // T9 - Replace: show related posts instead of tags.
     135        if ( 'replace' === $behavior ) {
     136            $related = $this->get_related_posts( $post_id );
     137            if ( empty( $related ) ) {
     138                return '';
     139            }
     140            $title = get_option( 's7n_tag_display_related_title', '' );
     141            if ( '' === $title ) {
     142                /* translators: Title above related posts list when behavior=replace. */
     143                $title = __( 'Related Topics', 'tag-display' );
     144            }
     145            $template = locate_template( 'tag-display-related-posts.php' );
     146            if ( ! $template ) {
     147                $template = plugin_dir_path( __FILE__ ) . '../public/partials/tag-display-related-posts.php';
     148            }
     149            ob_start();
     150            include $template; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable -- path validated via locate_template + plugin_dir_path.
     151            return ob_get_clean();
    130152        }
    131153
     
    237259            return in_array( $args['smart'], array( '1', 'true', 'yes' ), true );
    238260        }
     261        // T7/T8 - Mode takes precedence over legacy smart_enabled toggle.
     262        $mode = get_option( 's7n_tag_display_smart_mode', '' );
     263        if ( '' !== $mode ) {
     264            return 'disabled' !== $mode;
     265        }
    239266        return (bool) get_option( 's7n_tag_display_smart_enabled', false );
    240267    }
     
    254281    private function is_below_threshold( $tag_count, $post_id, $args ) {
    255282        $threshold = $this->get_threshold( $args );
     283        $mode      = get_option( 's7n_tag_display_smart_mode', '' );
     284
     285        // T8 - UX mode: always trigger regardless of tag count.
     286        if ( 'ux' === $mode ) {
     287            return true;
     288        }
    256289
    257290        if ( $tag_count < $threshold ) {
     
    259292        }
    260293
    261         // T2 — Density check (opt-in).
    262         if ( get_option( 's7n_tag_display_smart_use_density', false ) ) {
     294        // T8 - Density check: active in 'density' mode, or via legacy use_density option.
     295        $use_density = ( 'density' === $mode ) || ( '' === $mode && get_option( 's7n_tag_display_smart_use_density', false ) );
     296        if ( $use_density ) {
    263297            $density_threshold = (float) get_option( 's7n_tag_display_smart_density_threshold', 0.005 );
    264298            $density           = $this->get_density( $tag_count, $post_id );
     
    290324     * @since  1.9.0
    291325     * @since  2.0.0 Added 'hidden' and 'force' values.
     326     * @since  2.1.0 Added 'replace'.
    292327     * @param  array $args Display args.
    293      * @return string One of 'hide', 'hidden', 'collapse', 'seo'.
     328     * @return string One of 'hide', 'hidden', 'collapse', 'seo', 'replace'.
    294329     */
    295330    private function get_behavior( $args ) {
    296         $valid = array( 'hide', 'hidden', 'collapse', 'seo' );
     331        $valid = array( 'hide', 'hidden', 'collapse', 'seo', 'replace' );
    297332        if ( isset( $args['behavior'] ) && '' !== $args['behavior'] ) {
    298333            if ( in_array( $args['behavior'], $valid, true ) ) {
     
    303338        return in_array( $opt, $valid, true ) ? $opt : 'hide';
    304339    }
     340
     341    /**
     342     * Fetch related posts for a given post ID.
     343     *
     344     * Queries by shared tags first; if results < 3, fills with shared-category
     345     * posts. Results are transient-cached for 1 hour.
     346     *
     347     * @since  2.1.0
     348     * @param  int $post_id Post ID.
     349     * @return WP_Post[]
     350     */
     351    private function get_related_posts( $post_id ) {
     352        $transient_key = 's7n_related_' . $post_id;
     353        $cached        = get_transient( $transient_key );
     354        if ( false !== $cached ) {
     355            return $cached;
     356        }
     357
     358        $base_args = array(
     359            'post__not_in'           => array( $post_id ),
     360            'posts_per_page'         => 5,
     361            'post_status'            => 'publish',
     362            'no_found_rows'          => true,
     363            'update_post_meta_cache' => false,
     364            'ignore_sticky_posts'    => true,
     365        );
     366
     367        // Step 1 - related by shared tags.
     368        $tag_ids = wp_get_post_tags( $post_id, array( 'fields' => 'ids' ) );
     369        $related = array();
     370        if ( ! empty( $tag_ids ) ) {
     371            $query1  = new WP_Query( array_merge( $base_args, array( 'tag__in' => $tag_ids ) ) );
     372            $related = $query1->posts;
     373            wp_reset_postdata();
     374        }
     375
     376        // Step 2 - if fewer than 3, fill with category-related posts.
     377        if ( count( $related ) < 3 ) {
     378            $cat_ids = wp_get_post_categories( $post_id );
     379            if ( ! empty( $cat_ids ) ) {
     380                $exclude = array_merge( array( $post_id ), wp_list_pluck( $related, 'ID' ) );
     381                $query2  = new WP_Query(
     382                    array_merge(
     383                        $base_args,
     384                        array(
     385                            'category__in' => $cat_ids,
     386                            'post__not_in' => $exclude,
     387                        )
     388                    )
     389                );
     390                $related = array_slice( array_merge( $related, $query2->posts ), 0, 5 );
     391                wp_reset_postdata();
     392            }
     393        }
     394
     395        set_transient( $transient_key, $related, HOUR_IN_SECONDS );
     396        return $related;
     397    }
     398
     399    /**
     400     * Invalidate the related posts transient when a post's terms change.
     401     *
     402     * @since  2.1.0
     403     * @param  int $object_id Post ID whose terms were updated.
     404     * @return void
     405     */
     406    public function invalidate_related_cache( $object_id ) {
     407        delete_transient( 's7n_related_' . $object_id );
     408    }
    305409}
  • tag-display/trunk/languages/tag-display-it_IT.po

    r3498672 r3498697  
    243243msgstr "Cloud di tag"
    244244
    245 msgid "Tags sized proportionally to post count more posts, bigger tag."
    246 msgstr "Tag proporzionali al numero di articoli più articoli, tag più grande."
     245msgid "Tags sized proportionally to post count - more posts, bigger tag."
     246msgstr "Tag proporzionali al numero di articoli - più articoli, tag più grande."
    247247
    248248msgid "tags sized proportionally to post count."
     
    252252msgstr "Con bordo"
    253253
    254 msgid "Transparent background with a colored border modern pill-style."
    255 msgstr "Sfondo trasparente con bordo colorato stile pill moderno."
     254msgid "Transparent background with a colored border - modern pill-style."
     255msgstr "Sfondo trasparente con bordo colorato - stile pill moderno."
    256256
    257257msgid "transparent background with colored pill border."
     
    261261msgstr "Hashtag"
    262262
    263 msgid "Social-style tags prefixed with # no border, no background."
    264 msgstr "Tag in stile social con # senza bordo, senza sfondo."
     263msgid "Social-style tags prefixed with # - no border, no background."
     264msgstr "Tag in stile social con # - senza bordo, senza sfondo."
    265265
    266266msgid "social-style #tag format."
     
    396396msgstr "Visibilità intelligente"
    397397
    398 msgid "Automatically adapt tag display based on tag count improving both SEO and user experience."
     398msgid "Automatically adapt tag display based on tag count - improving both SEO and user experience."
    399399msgstr "Adatta automaticamente la visualizzazione dei tag in base al loro numero, migliorando SEO e UX."
    400400
     
    417417msgstr "Comportamento sotto la soglia"
    418418
    419 msgid "Hide suppress tags entirely (no DOM output)"
    420 msgstr "Nascondi sopprime i tag completamente (nessun output nel DOM)"
    421 
    422 msgid "Hidden render tags invisibly, togglable via JavaScript"
    423 msgstr "Nascosto renderizza i tag invisibili, attivabili tramite JavaScript"
    424 
    425 msgid "Collapse show a \"Show tags\" button to expand"
    426 msgstr "Comprimi mostra un bottone \"Mostra tag\" per espandere"
    427 
    428 msgid "SEO hidden invisible to visitors, visible to crawlers"
    429 msgstr "Nascosto SEO invisibile ai visitatori, visibile ai crawler"
     419msgid "Hide - suppress tags entirely (no DOM output)"
     420msgstr "Nascondi - sopprime i tag completamente (nessun output nel DOM)"
     421
     422msgid "Hidden - render tags invisibly, togglable via JavaScript"
     423msgstr "Nascosto - renderizza i tag invisibili, attivabili tramite JavaScript"
     424
     425msgid "Collapse - show a \"Show tags\" button to expand"
     426msgstr "Comprimi - mostra un bottone \"Mostra tag\" per espandere"
     427
     428msgid "SEO hidden - invisible to visitors, visible to crawlers"
     429msgstr "Nascosto SEO - invisibile ai visitatori, visibile ai crawler"
    430430
    431431msgid "What to do when a post has fewer tags than the threshold."
     
    453453msgstr "La visibilità intelligente può essere controllata per ogni istanza tramite shortcode:"
    454454
    455 msgid "true / false override the global toggle"
    456 msgstr "true / false sovrascrive l'interruttore globale"
     455msgid "true / false - override the global toggle"
     456msgstr "true / false - sovrascrive l'interruttore globale"
    457457
    458458msgid "minimum tag count threshold for this instance"
    459459msgstr "soglia minima del numero di tag per questa istanza"
     460
     461msgid "Mode"
     462msgstr "Modalità"
     463
     464msgid "Default (use Enable toggle below)"
     465msgstr "Predefinito (usa l'interruttore Attiva qui sotto)"
     466
     467msgid "Auto - activate when tag count is below threshold"
     468msgstr "Auto - si attiva quando il conteggio dei tag è sotto la soglia"
     469
     470msgid "Density - also activate when tag density is low"
     471msgstr "Densità - si attiva anche quando la densità dei tag è bassa"
     472
     473msgid "UX - always activate (behavior decides the response)"
     474msgstr "UX - si attiva sempre (il comportamento decide la risposta)"
     475
     476msgid "Disabled - Smart Visibility is off"
     477msgstr "Disabilitato - Visibilità intelligente spenta"
     478
     479msgid "When set, Mode overrides the Enable toggle. Density mode also uses the density threshold below."
     480msgstr "Se impostata, la Modalità sovrascrive l'interruttore Attiva. La modalità Densità usa anche la soglia di densità qui sotto."
     481
     482msgid "Replace - show related posts instead of tags"
     483msgstr "Sostituisci - mostra articoli correlati al posto dei tag"
     484
     485msgid "Related Topics Title"
     486msgstr "Titolo articoli correlati"
     487
     488msgid "Title shown above related posts when Behavior is set to Replace. Leave empty to use the default."
     489msgstr "Titolo mostrato sopra gli articoli correlati quando il Comportamento è Sostituisci. Lascia vuoto per usare il valore predefinito."
     490
     491msgid "Related Topics"
     492msgstr "Argomenti correlati"
     493
     494msgid "This toggle is overridden by the Mode setting above. Change Mode to \"Default\" to use this toggle again."
     495msgstr "Questo interruttore e' ignorato dalla Modalita' impostata qui sopra. Cambia la Modalita' in \"Predefinito\" per usarlo di nuovo."
     496
     497msgid "Active when Mode is set to \"Density\". Minimum ratio of tags to words: below this value the selected behavior triggers."
     498msgstr "Attivo quando la Modalita' e' impostata su \"Densita'\". Rapporto minimo tag/parole: sotto questo valore il comportamento selezionato si attiva."
     499
     500msgid "Default: 0.005 (1 tag per 200 words). Lower values are stricter."
     501msgstr "Predefinito: 0.005 (1 tag ogni 200 parole). Valori piu' bassi sono piu' restrittivi."
     502
     503msgid "Density Threshold"
     504msgstr "Soglia densita'"
  • tag-display/trunk/languages/tag-display.pot

    r3498672 r3498697  
    409409
    410410#: /mnt/progetti/Progetti/tag-display/trunk/admin/partials/tag-display-admin-display.php:169
    411 msgid "Tags sized proportionally to post count more posts, bigger tag."
     411msgid "Tags sized proportionally to post count - more posts, bigger tag."
    412412msgstr ""
    413413
     
    417417
    418418#: /mnt/progetti/Progetti/tag-display/trunk/admin/partials/tag-display-admin-display.php:210
    419 msgid "Transparent background with a colored border modern pill-style."
     419msgid "Transparent background with a colored border - modern pill-style."
    420420msgstr ""
    421421
    422422#: /mnt/progetti/Progetti/tag-display/trunk/admin/partials/tag-display-admin-display.php:234
    423 msgid "Social-style tags prefixed with # no border, no background."
     423msgid "Social-style tags prefixed with # - no border, no background."
    424424msgstr ""
    425425
     
    593593
    594594#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php:1021
    595 msgid "Automatically adapt tag display based on tag count improving both SEO and user experience."
     595msgid "Automatically adapt tag display based on tag count - improving both SEO and user experience."
    596596msgstr ""
    597597
     
    621621
    622622#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php:1075
    623 msgid "Hide suppress tags entirely (no DOM output)"
     623msgid "Hide - suppress tags entirely (no DOM output)"
    624624msgstr ""
    625625
    626626#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php:1076
    627 msgid "Hidden render tags invisibly, togglable via JavaScript"
     627msgid "Hidden - render tags invisibly, togglable via JavaScript"
    628628msgstr ""
    629629
    630630#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php:1077
    631 msgid "Collapse show a \"Show tags\" button to expand"
     631msgid "Collapse - show a \"Show tags\" button to expand"
    632632msgstr ""
    633633
    634634#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php:1078
    635 msgid "SEO hidden invisible to visitors, visible to crawlers"
     635msgid "SEO hidden - invisible to visitors, visible to crawlers"
    636636msgstr ""
    637637
     
    669669
    670670#: /mnt/progetti/Progetti/tag-display/trunk/admin/partials/tag-display-admin-display.php:122
    671 msgid "true / false override the global toggle"
     671msgid "true / false - override the global toggle"
    672672msgstr ""
    673673
     
    675675msgid "minimum tag count threshold for this instance"
    676676msgstr ""
     677
     678#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     679msgid "Mode"
     680msgstr ""
     681
     682#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     683msgid "Default (use Enable toggle below)"
     684msgstr ""
     685
     686#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     687msgid "Auto - activate when tag count is below threshold"
     688msgstr ""
     689
     690#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     691msgid "Density - also activate when tag density is low"
     692msgstr ""
     693
     694#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     695msgid "UX - always activate (behavior decides the response)"
     696msgstr ""
     697
     698#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     699msgid "Disabled - Smart Visibility is off"
     700msgstr ""
     701
     702#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     703msgid "When set, Mode overrides the Enable toggle. Density mode also uses the density threshold below."
     704msgstr ""
     705
     706#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     707msgid "Replace - show related posts instead of tags"
     708msgstr ""
     709
     710#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     711msgid "Related Topics Title"
     712msgstr ""
     713
     714#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     715msgid "Title shown above related posts when Behavior is set to Replace. Leave empty to use the default."
     716msgstr ""
     717
     718#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-smart-visibility.php
     719msgid "Related Topics"
     720msgstr ""
     721
     722#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     723msgid "This toggle is overridden by the Mode setting above. Change Mode to \"Default\" to use this toggle again."
     724msgstr ""
     725
     726#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     727msgid "Active when Mode is set to \"Density\". Minimum ratio of tags to words: below this value the selected behavior triggers."
     728msgstr ""
     729
     730#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     731msgid "Default: 0.005 (1 tag per 200 words). Lower values are stricter."
     732msgstr ""
     733
     734#: /mnt/progetti/Progetti/tag-display/trunk/includes/class-tag-display-admin.php
     735msgid "Density Threshold"
     736msgstr ""
  • tag-display/trunk/public/css/tag-display-public.css

    r3498672 r3498697  
    2525}
    2626
    27 /* Focus styles visible for keyboard navigation (T2) */
     27/* Focus styles - visible for keyboard navigation (T2) */
    2828.tag-display-container a:focus {
    2929    outline: none;
     
    273273    color: #005177;
    274274}
     275
     276/* replace: related posts list shown instead of tags */
     277.s7n-related-posts {
     278    margin: 0;
     279}
     280
     281.s7n-related-posts__title {
     282    font-weight: bold;
     283    margin: 0 0 8px;
     284}
     285
     286.s7n-related-posts__list {
     287    list-style: none;
     288    margin: 0;
     289    padding: 0;
     290}
     291
     292.s7n-related-posts__item {
     293    margin: 0 0 4px;
     294}
     295
     296.s7n-related-posts__item a {
     297    text-decoration: underline;
     298}
     299
     300@media (max-width: 768px) {
     301    .s7n-related-posts__item {
     302        margin-bottom: 6px;
     303    }
     304}
     305
     306@media (prefers-reduced-motion: reduce) {
     307    .s7n-related-posts__item a {
     308        transition: none;
     309    }
     310}
  • tag-display/trunk/public/js/tag-display-public.js

    r3495992 r3498697  
    2222        );
    2323
    24         // Smart Visibility collapse/expand
     24        // Smart Visibility - collapse/expand
    2525        $(document).on('click', '.s7n-tags-expand-btn', function() {
    2626            var $btn      = $(this);
  • tag-display/trunk/public/partials/tag-display-template-cloud.php

    r3496031 r3498697  
    2929$max_count = max( $counts );
    3030
    31 // T23 Build link rel and target from display args
     31// T23 - Build link rel and target from display args
    3232$rel_parts = array( 'tag' );
    3333if ( ! empty( $display_nofollow ) ) {
     
    4040$link_target = ! empty( $display_new_tab ) ? ' target="_blank"' : '';
    4141
    42 // T25 Use title from display args (set by get_tag_display())
     42// T25 - Use title from display args (set by get_tag_display())
    4343$title_text = isset( $display_title ) ? $display_title : get_option( 's7n_tag_display_title', 'Tags:' );
    4444?>
     
    6868            $style   = sprintf( 'font-size: %dpx; opacity: %.2f;', $font_size, $opacity );
    6969
    70             // T24 Optionally show post count
     70            // T24 - Optionally show post count
    7171            $count_label = ! empty( $display_show_count ) ? ' (' . $count . ')' : '';
    7272            ?>
  • tag-display/trunk/public/partials/tag-display-template-default.php

    r3496031 r3498697  
    1717}
    1818
    19 // T23 Build link rel and target from display args
     19// T23 - Build link rel and target from display args
    2020$rel_parts = array( 'tag' );
    2121if ( ! empty( $display_nofollow ) ) {
     
    2828$link_target = ! empty( $display_new_tab ) ? ' target="_blank"' : '';
    2929
    30 // T25 Use title from display args (set by get_tag_display())
     30// T25 - Use title from display args (set by get_tag_display())
    3131$title_text = isset( $display_title ) ? $display_title : get_option( 's7n_tag_display_title', 'Tags:' );
    3232?>
     
    4141        <?php
    4242        foreach ( $tags as $td_tag ) :
    43             // T24 Optionally show post count
     43            // T24 - Optionally show post count
    4444            $count_label = ! empty( $display_show_count ) ? ' (' . (int) $td_tag->count . ')' : '';
    4545            ?>
  • tag-display/trunk/public/partials/tag-display-template-hashtag.php

    r3496031 r3498697  
    22/**
    33 * Hashtag template for displaying tags.
    4  * Social-style tags prefixed with # no border, no background.
     4 * Social-style tags prefixed with # - no border, no background.
    55 *
    66 * @since      1.4.0
  • tag-display/trunk/public/partials/tag-display-template-minimal.php

    r3498672 r3498697  
    1717}
    1818
    19 // T23 Build link rel and target from display args
     19// T23 - Build link rel and target from display args
    2020$rel_parts = array( 'tag' );
    2121if ( ! empty( $display_nofollow ) ) {
     
    2828$link_target = ! empty( $display_new_tab ) ? ' target="_blank"' : '';
    2929
    30 // T25 Use title from display args (set by get_tag_display())
     30// T25 - Use title from display args (set by get_tag_display())
    3131$title_text = isset( $display_title ) ? $display_title : get_option( 's7n_tag_display_title', 'Tags:' );
    3232?>
     
    4444        foreach ( $tags as $td_tag ) :
    4545            ++$i;
    46             // T24 Optionally show post count
     46            // T24 - Optionally show post count
    4747            $count_label = ! empty( $display_show_count ) ? ' (' . (int) $td_tag->count . ')' : '';
    4848            $sep         = $i < $tag_count ? '<span class="tag-separator">,</span>' : '';
  • tag-display/trunk/public/partials/tag-display-template-outlined.php

    r3496031 r3498697  
    22/**
    33 * Outlined template for displaying tags.
    4  * Transparent background with colored border modern minimal style.
     4 * Transparent background with colored border - modern minimal style.
    55 *
    66 * @since      1.4.0
  • tag-display/trunk/readme.txt

    r3498672 r3498697  
    55Tested up to: 6.8
    66Requires PHP: 7.2 
    7 Stable tag: 2.0.0
     7Stable tag: 2.1.0
    88License: GPLv2 or later 
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html 
     
    3333- SEO options: rel="nofollow" and target="_blank" for tag links.
    3434- Theme template override: place a custom template file in your theme folder to take over the output.
    35 - **Smart Visibility**: automatically hide, collapse, or SEO-hide tags when the count falls below a configurable threshold improving both SEO and UX.
     35- **Smart Visibility**: automatically hide, collapse, or SEO-hide tags when the count falls below a configurable threshold - improving both SEO and UX.
    3636- **Content Density Analysis**: trigger Smart Visibility based on the ratio of tags to words in the post, not just tag count.
    3737- **Per-instance FORCE bypass**: disable Smart Visibility for a single shortcode or block without touching global settings.
     
    116116
    117117= What is Smart Visibility and how do I use it? =
    118 Smart Visibility automatically adapts tag display based on how many tags a post has improving both SEO and user experience. When the count falls below a configurable threshold, the plugin applies the behavior you choose:
     118Smart Visibility automatically adapts tag display based on how many tags a post has - improving both SEO and user experience. When the count falls below a configurable threshold, the plugin applies the behavior you choose:
    119119
    120120* **Hide** - suppresses the tag block entirely (no HTML output). Best for SEO: avoids thin tag sections.
     
    123123* **SEO hidden** - tags are visually invisible to visitors but present in the DOM for search crawlers.
    124124
    125 To enable it, go to **Tag Display → Smart Visibility**, turn on the toggle, set your **Minimum Tag Threshold** (default: 3), and pick a behavior. When a post has at least as many tags as the threshold, it displays normally Smart Visibility is completely transparent.
    126 
    127 **Content Density Analysis (advanced):** you can also trigger Smart Visibility based on tag density the ratio of tags to words in the post. Enable "Content Density Analysis" in the Smart Visibility tab and set a density threshold (default: 0.005, which equals 1 tag per 200 words). If the density is below the threshold, the selected behavior applies even if the tag count meets the minimum.
     125To enable it, go to **Tag Display → Smart Visibility**, turn on the toggle, set your **Minimum Tag Threshold** (default: 3), and pick a behavior. When a post has at least as many tags as the threshold, it displays normally - Smart Visibility is completely transparent.
     126
     127**Content Density Analysis (advanced):** you can also trigger Smart Visibility based on tag density - the ratio of tags to words in the post. Enable "Content Density Analysis" in the Smart Visibility tab and set a density threshold (default: 0.005, which equals 1 tag per 200 words). If the density is below the threshold, the selected behavior applies even if the tag count meets the minimum.
    128128
    129129**Per-instance override via shortcode:**
     
    149149== Changelog ==
    150150
     151= 2.1.0 =
     152* Added Mode field in Smart Visibility admin: Auto, Density, UX, Disabled - replaces the Enable toggle when set.
     153* Added behavior `replace`: when tags are below threshold, a related posts list is shown instead (WP_Query cascade: shared tags → shared categories, up to 5 results, transient-cached 1h).
     154* New template `tag-display-related-posts.php` with configurable title via admin field.
     155* Transient cache automatically invalidated when post terms change (`set_object_terms` hook).
     156* Admin: new "Related Topics Title" field; behavior dropdown includes "Replace".
     157* Added CSS for `.s7n-related-posts` (neutral, theme-inheriting, responsive).
     158* Updated Italian translations for all new strings.
     159
    151160= 2.0.0 =
    152161* Added content density analysis: Smart Visibility can now trigger based on tag density (tags per word) in addition to tag count.
    153 * New behavior: "Hidden" renders tags with `display:none` (DOM present, togglable via JavaScript) without a full PHP re-render.
     162* New behavior: "Hidden" - renders tags with `display:none` (DOM present, togglable via JavaScript) without a full PHP re-render.
    154163* Added FORCE bypass: `[s7n_tag_display smart="false"]` or `behavior="force"` disables Smart Visibility for a single instance.
    155164* Admin: new "Content Density Analysis" field in Smart Visibility tab with density threshold setting (default: 0.005).
  • tag-display/trunk/tag-display.php

    r3498672 r3498697  
    1111 * Plugin URI:        https://ismailnasry.it/portfolio-archive/tag-display/
    1212 * Description:       Display clickable tags in pages/articles with customizable templates and display options.
    13  * Version:           2.0.0
     13 * Version:           2.1.0
    1414 * Author:            Ismail Nasry
    1515 * Author URI:        https://ismailnasry.it
     
    2929 * Currently plugin version.
    3030 */
    31 define( 'S7N_TAG_DISPLAY_VERSION', '2.0.0' );
     31define( 'S7N_TAG_DISPLAY_VERSION', '2.1.0' );
    3232
    3333/**
Note: See TracChangeset for help on using the changeset viewer.