Changeset 356198
- Timestamp:
- 10/29/2026 04:09:14 PM (17 hours ago)
- Location:
- tso-blog/1.0.9
- Files:
-
- 3 added
- 5 deleted
- 15 edited
- 1 copied
-
. (copied) (copied from tso-blog/1.0.8 )
-
LICENSE (added)
-
class-tsotheme-customize-repeater-control.php (modified) (3 diffs)
-
functions.php (modified) (16 diffs)
-
header.php (modified) (2 diffs)
-
languages/ca.mo (deleted)
-
languages/en_US.mo (deleted)
-
languages/es_ES.mo (deleted)
-
languages/tso-blog-ca.mo (modified) ( previous)
-
languages/tso-blog-ca.po (modified) (6 diffs)
-
languages/tso-blog-en_US.mo (deleted)
-
languages/tso-blog-en_US.po (deleted)
-
languages/tso-blog-es_ES.mo (modified) ( previous)
-
languages/tso-blog-es_ES.po (modified) (6 diffs)
-
readme.txt (modified) (4 diffs)
-
screenshot.png (modified) ( previous)
-
style.css (modified) (2 diffs)
-
tso-announcement.js (added)
-
tso-color-mode.js (added)
-
tso-customize-repeater.js (modified) (7 diffs)
-
tso-lightbox.js (modified) (2 diffs)
-
tso-live-search.js (modified) (1 diff)
-
tso-load-more.js (modified) (1 diff)
-
tsothm-announcement.js (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
tso-blog/1.0.9/class-tsotheme-customize-repeater-control.php
r352803 r356198 58 58 59 59 /** 60 * Maximum number of rows. The pricing repeater uses 5. 61 * 62 * @var int 63 */ 64 public $max_items = 50; 65 66 /** 60 67 * Enqueue control scripts/styles. 61 68 */ … … 94 101 */ 95 102 protected function get_rows() { 96 $raw = $this->value();103 $raw = $this->value(); 97 104 $rows = json_decode( is_string( $raw ) ? $raw : '', true ); 98 return is_array( $rows ) ? array_values( $rows ) : array(); 105 $rows = is_array( $rows ) ? array_values( $rows ) : array(); 106 $max = absint( $this->max_items ); 107 if ( $max > 0 && count( $rows ) > $max ) { 108 $rows = array_slice( $rows, 0, $max ); 109 } 110 return $rows; 99 111 } 100 112 … … 118 130 data-fields="<?php echo esc_attr( wp_json_encode( $this->fields ) ); ?>" 119 131 data-add-label="<?php echo esc_attr( $this->add_label ? $this->add_label : __( 'Add row', 'tso-blog' ) ); ?>" 132 data-max="<?php echo esc_attr( (string) max( 1, absint( $this->max_items ) ) ); ?>" 120 133 > 121 134 <ul class="tso-repeater-list"></ul> -
tso-blog/1.0.9/functions.php
r353346 r356198 7 7 8 8 if ( ! defined( 'TSOTHM_VERSION' ) ) { 9 define( 'TSOTHM_VERSION', '1.0. 8' );9 define( 'TSOTHM_VERSION', '1.0.9' ); 10 10 } 11 11 … … 1240 1240 true 1241 1241 ); 1242 wp_localize_script( 1243 'tsothm-lightbox', 1244 'tsothmLightbox', 1245 array( 1246 'viewer' => __( 'Image viewer', 'tso-blog' ), 1247 'close' => __( 'Close', 'tso-blog' ), 1248 'prev' => __( 'Previous image', 'tso-blog' ), 1249 'next' => __( 'Next image', 'tso-blog' ), 1250 ) 1251 ); 1242 1252 } 1243 1253 } … … 2359 2369 $wp_customize->get_section( 'title_tagline' )->priority = 20; 2360 2370 } 2361 2362 $wp_customize->add_panel( 2363 'tsothm_appearance_panel', 2364 array( 2365 'title' => __( 'Appearance', 'tso-blog' ), 2366 'description' => __( 'Logo, site width, sidebar, header social links and header image.', 'tso-blog' ), 2367 'priority' => 25, 2368 ) 2369 ); 2370 2371 $wp_customize->add_panel( 2372 'tsothm_footer_panel', 2373 array( 2374 'title' => __( 'Footer', 'tso-blog' ), 2375 'description' => __( 'Help for widget columns and footer texts. Footer colors are under Colors → Footer.', 'tso-blog' ), 2376 'priority' => 40, 2377 ) 2378 ); 2379 2380 $wp_customize->add_panel( 2381 'tsothm_content_panel', 2382 array( 2383 'title' => __( 'Templates', 'tso-blog' ), 2384 'description' => __( 'Contact, Team, Pricing and Landing templates, and the top announcement.', 'tso-blog' ), 2385 'priority' => 45, 2386 ) 2387 ); 2388 2389 if ( $wp_customize->get_section( 'header_image' ) ) { 2390 $wp_customize->get_section( 'header_image' )->panel = 'tsothm_appearance_panel'; 2391 $wp_customize->get_section( 'header_image' )->priority = 40; 2392 } 2393 if ( $wp_customize->get_section( 'background_image' ) ) { 2394 $wp_customize->get_section( 'background_image' )->panel = 'tsothm_appearance_panel'; 2395 $wp_customize->get_section( 'background_image' )->priority = 15; 2396 $wp_customize->get_section( 'background_image' )->description = __( 'Optional background image for the whole site, behind the content. You can upload it and adjust its position, size, repeat and scrolling (parallax).', 'tso-blog' ); 2397 } 2398 if ( $wp_customize->get_section( 'colors' ) ) { 2399 // Core “Colores” vacío: ocultar para no duplicar el panel TSO. 2400 $wp_customize->remove_section( 'colors' ); 2401 } 2402 2403 /* Logo — imagen (core) + tamaños */ 2404 $wp_customize->add_section( 2405 'tsothm_logo_section', 2406 array( 2407 'title' => __( 'Logo', 'tso-blog' ), 2408 'description' => __( 'Upload the logo and set its width on desktop and mobile. There is no sticky logo: the header does not stay fixed on scroll.', 'tso-blog' ), 2409 'panel' => 'tsothm_appearance_panel', 2410 'priority' => 10, 2411 ) 2412 ); 2413 2414 if ( $wp_customize->get_control( 'custom_logo' ) ) { 2415 $wp_customize->get_control( 'custom_logo' )->section = 'tsothm_logo_section'; 2416 $wp_customize->get_control( 'custom_logo' )->priority = 5; 2417 $wp_customize->get_control( 'custom_logo' )->label = __( 'Logo', 'tso-blog' ); 2418 } 2419 2371 // Keep Site Title and Tagline after the Site Logo width controls (priorities 9 and 10). 2372 if ( $wp_customize->get_control( 'blogname' ) ) { 2373 $wp_customize->get_control( 'blogname' )->priority = 20; 2374 } 2375 if ( $wp_customize->get_control( 'blogdescription' ) ) { 2376 $wp_customize->get_control( 'blogdescription' )->priority = 30; 2377 } 2378 2379 /* 2380 * Logo widths live next to the core Site Logo control (Site Identity). 2381 * Do not move or replace custom_logo: that is the WordPress Site Logo feature. 2382 */ 2420 2383 $wp_customize->add_setting( 2421 2384 'tsothm_logo_width', … … 2430 2393 array( 2431 2394 'label' => __( 'Logo width (px)', 'tso-blog' ), 2432 'description' => __( 'Desktop display width. Theme maximum: 500 px (minimum 40). Height adjusts automatically. For a sharp result, use a logo file at least this wide.', 'tso-blog' ), 2433 'section' => 'tsothm_logo_section', 2395 'description' => __( 'Desktop display width of the Site Logo. Theme maximum: 500 px (minimum 40). Height adjusts automatically. For a sharp result, use a logo file at least this wide.', 'tso-blog' ), 2396 'section' => 'title_tagline', 2397 'type' => 'number', 2398 'priority' => 9, 2399 'input_attrs' => array( 2400 'min' => 40, 2401 'max' => 500, 2402 'step' => 1, 2403 ), 2404 ) 2405 ); 2406 2407 $wp_customize->add_setting( 2408 'tsothm_logo_width_mobile', 2409 array( 2410 'default' => '180', 2411 'sanitize_callback' => 'tsothm_sanitize_logo_width_mobile', 2412 'transport' => 'refresh', 2413 ) 2414 ); 2415 $wp_customize->add_control( 2416 'tsothm_logo_width_mobile', 2417 array( 2418 'label' => __( 'Logo width on mobile (px)', 'tso-blog' ), 2419 'description' => __( 'Mobile display width of the Site Logo (screens ≤ 768 px). Theme maximum: 500 px (minimum 40). Use the Customizer mobile preview to see it. For a sharp result, use a logo file at least this wide.', 'tso-blog' ), 2420 'section' => 'title_tagline', 2434 2421 'type' => 'number', 2435 2422 'priority' => 10, … … 2442 2429 ); 2443 2430 2444 $wp_customize->add_setting( 2445 'tsothm_logo_width_mobile', 2446 array( 2447 'default' => '180', 2448 'sanitize_callback' => 'tsothm_sanitize_logo_width_mobile', 2449 'transport' => 'refresh', 2450 ) 2451 ); 2452 $wp_customize->add_control( 2453 'tsothm_logo_width_mobile', 2454 array( 2455 'label' => __( 'Logo width on mobile (px)', 'tso-blog' ), 2456 'description' => __( 'Mobile display width (screens ≤ 768 px). Theme maximum: 500 px (minimum 40). Use the Customizer mobile preview to see it. For a sharp result, use a logo file at least this wide.', 'tso-blog' ), 2457 'section' => 'tsothm_logo_section', 2458 'type' => 'number', 2459 'priority' => 20, 2460 'input_attrs' => array( 2461 'min' => 40, 2462 'max' => 500, 2463 'step' => 1, 2464 ), 2465 ) 2466 ); 2431 $wp_customize->add_panel( 2432 'tsothm_appearance_panel', 2433 array( 2434 'title' => __( 'Appearance', 'tso-blog' ), 2435 'description' => __( 'Site width, sidebar, header social links and header image. The site logo is set under Site Identity.', 'tso-blog' ), 2436 'priority' => 25, 2437 ) 2438 ); 2439 2440 $wp_customize->add_panel( 2441 'tsothm_footer_panel', 2442 array( 2443 'title' => __( 'Footer', 'tso-blog' ), 2444 'description' => __( 'Help for widget columns and footer texts. Footer colors are under Colors → Footer.', 'tso-blog' ), 2445 'priority' => 40, 2446 ) 2447 ); 2448 2449 $wp_customize->add_panel( 2450 'tsothm_content_panel', 2451 array( 2452 'title' => __( 'Templates', 'tso-blog' ), 2453 'description' => __( 'Contact, Team, Pricing and Landing templates, and the top announcement.', 'tso-blog' ), 2454 'priority' => 45, 2455 ) 2456 ); 2457 2458 if ( $wp_customize->get_section( 'header_image' ) ) { 2459 $wp_customize->get_section( 'header_image' )->panel = 'tsothm_appearance_panel'; 2460 $wp_customize->get_section( 'header_image' )->priority = 40; 2461 } 2462 if ( $wp_customize->get_section( 'background_image' ) ) { 2463 $wp_customize->get_section( 'background_image' )->panel = 'tsothm_appearance_panel'; 2464 $wp_customize->get_section( 'background_image' )->priority = 15; 2465 $wp_customize->get_section( 'background_image' )->description = __( 'Optional background image for the whole site, behind the content. You can upload it and adjust its position, size, repeat and scrolling (parallax).', 'tso-blog' ); 2466 } 2467 if ( $wp_customize->get_section( 'colors' ) ) { 2468 // Core “Colores” vacío: ocultar para no duplicar el panel TSO. 2469 $wp_customize->remove_section( 'colors' ); 2470 } 2467 2471 2468 2472 /* Diseño — ancho del sitio */ … … 3817 3821 'description' => __( 'In Google Maps: Share → Embed a map → copy the src attribute URL (or paste the full embed code). Only Google Maps embed URLs are accepted. Empty = no map.', 'tso-blog' ), 3818 3822 'section' => 'tsothm_contact_section', 3819 'type' => 'text area',3823 'type' => 'text', 3820 3824 ) 3821 3825 ); … … 3892 3896 array( 3893 3897 'title' => __( 'Pricing', 'tso-blog' ), 3894 'description' => __( ' Plans for the "Pricing" page template. If left empty, the page will showthe block content ("Pricing (3 plans)" pattern).', 'tso-blog' ),3898 'description' => __( 'Up to 5 plans for the "Pricing" page template. If left empty, the page shows the block content ("Pricing (3 plans)" pattern).', 'tso-blog' ), 3895 3899 'panel' => 'tsothm_content_panel', 3896 3900 'priority' => 24, … … 3910 3914 'tsothm_pricing_plans', 3911 3915 array( 3912 'label' => __( 'Plans', 'tso-blog' ), 3913 'section' => 'tsothm_pricing_section', 3914 'fields' => tsothm_get_pricing_fields(), 3915 'add_label' => __( 'Add plan', 'tso-blog' ), 3916 'label' => __( 'Plans', 'tso-blog' ), 3917 'description' => __( 'Maximum 5 plans. Separate features with a vertical bar, for example: Support | Updates | Backups.', 'tso-blog' ), 3918 'section' => 'tsothm_pricing_section', 3919 'fields' => tsothm_get_pricing_fields(), 3920 'add_label' => __( 'Add plan', 'tso-blog' ), 3921 'max_items' => 5, 3916 3922 ) 3917 3923 ) … … 5703 5709 array( 5704 5710 'key' => 'features', 5705 'type' => 'text area',5706 'label' => __( 'Features (one per line)', 'tso-blog' ),5711 'type' => 'text', 5712 'label' => __( 'Features, separated by |', 'tso-blog' ), 5707 5713 ), 5708 5714 array( … … 5743 5749 array( 5744 5750 'key' => 'text', 5745 'type' => 'text area',5751 'type' => 'text', 5746 5752 'label' => __( 'Short text', 'tso-blog' ), 5747 5753 ), … … 5767 5773 default: 5768 5774 $text = is_string( $value ) ? $value : ''; 5775 // Older pricing rows stored one feature per line. Keep them as separate items. 5776 if ( isset( $field['key'] ) && 'features' === $field['key'] ) { 5777 $text = str_replace( array( "\r\n", "\r", "\n" ), ' | ', $text ); 5778 } 5769 5779 // Los campos de texto que parecen URL (link, button_url) se sanean como URL. 5770 5780 if ( isset( $field['key'] ) && false !== strpos( $field['key'], 'url' ) ) { … … 5780 5790 /** 5781 5791 * Generic repeater sanitizer: decodes JSON, keeps only known fields, 5782 * sanitizes each value by type, re-encodes to JSON. Caps at 50 rows.5792 * sanitizes each value by type, re-encodes to JSON. 5783 5793 * 5784 5794 * @param string $value Raw JSON value from the Customizer control. 5785 5795 * @param array $fields Field schema (tsothm_get_*_fields()). 5796 * @param int $max Maximum rows. Pricing uses 5; other repeaters default to 50. 5786 5797 * @return string Sanitized JSON. 5787 5798 */ 5788 function tsothm_sanitize_repeater_json( $value, $fields ) {5799 function tsothm_sanitize_repeater_json( $value, $fields, $max = 50 ) { 5789 5800 $rows = json_decode( is_string( $value ) ? $value : '', true ); 5790 5801 if ( ! is_array( $rows ) ) { … … 5792 5803 } 5793 5804 5805 $max = absint( $max ); 5806 if ( $max < 1 ) { 5807 $max = 50; 5808 } 5809 5794 5810 $clean = array(); 5795 foreach ( array_slice( $rows, 0, 50) as $row ) {5811 foreach ( array_slice( $rows, 0, $max ) as $row ) { 5796 5812 if ( ! is_array( $row ) ) { 5797 5813 continue; … … 5828 5844 */ 5829 5845 function tsothm_sanitize_pricing_plans( $value ) { 5830 return tsothm_sanitize_repeater_json( $value, tsothm_get_pricing_fields() );5846 return tsothm_sanitize_repeater_json( $value, tsothm_get_pricing_fields(), 5 ); 5831 5847 } 5832 5848 … … 5980 5996 if ( ! empty( $plan['features'] ) ) { 5981 5997 echo '<ul class="tso-pricing-features">'; 5982 foreach ( preg_split( '/\ r\n|\r|\n/', (string) $plan['features'] ) as $line ) {5998 foreach ( preg_split( '/\s*\|\s*|\r\n|\r|\n/', (string) $plan['features'] ) as $line ) { 5983 5999 $line = trim( $line ); 5984 6000 if ( '' === $line ) { … … 6714 6730 }; 6715 6731 6716 // Site title ( fallback text logo when no custom logo / theme logo file).6732 // Site title (shown when Site Identity has no Site Logo). 6717 6733 $set_post_message( 'blogname' ); 6718 6734 $wp_customize->selective_refresh->add_partial( -
tso-blog/1.0.9/header.php
r353346 r356198 17 17 <?php the_custom_logo(); ?> 18 18 <?php else : ?> 19 <a href="<?php echo esc_url( home_url( '/' ) ); ?>"> 20 <?php 21 $tsothm_logo = get_stylesheet_directory() . '/images/logo.png'; 22 if ( file_exists( $tsothm_logo ) ) { 23 echo '<img src="' . esc_url( get_stylesheet_directory_uri() . '/images/logo.png' ) . '" alt="' . esc_attr( get_bloginfo( 'name' ) ) . '" width="300" height="124">'; 24 } else { 25 echo '<span class="site-title-text">' . esc_html( get_bloginfo( 'name' ) ) . '</span>'; 26 } 27 ?> 19 <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"> 20 <span class="site-title-text"><?php echo esc_html( get_bloginfo( 'name', 'display' ) ); ?></span> 28 21 </a> 29 22 <?php endif; ?> … … 65 58 <?php tsothm_header_announcement(); ?> 66 59 67 <nav id="site-navigation" class="main-navigation" aria-label=" Menú principal">60 <nav id="site-navigation" class="main-navigation" aria-label="<?php esc_attr_e( 'Primary Menu', 'tso-blog' ); ?>"> 68 61 <?php wp_nav_menu( array( 69 62 'theme_location' => 'main-menu', -
tso-blog/1.0.9/languages/tso-blog-ca.po
r353345 r356198 451 451 #: functions.php:2352 452 452 msgid "" 453 "Desktop display width. Theme maximum: 500 px (minimum 40). Height adjusts " 454 "automatically. For a sharp result, use a logo file at least this wide." 455 msgstr "" 456 "Amplada de visualització a l'escriptori. Màxim del tema: 500 px (mínim 40). " 457 "L'alçada s'ajusta sola. Per un resultat nítid, useu un fitxer de logo " 458 "d'almenys aquesta amplada." 453 "Desktop display width of the Site Logo. Theme maximum: 500 px (minimum 40). " 454 "Height adjusts automatically. For a sharp result, use a logo file at least " 455 "this wide." 456 msgstr "" 457 "Amplada de visualització del logotip del lloc a l'escriptori. Màxim del " 458 "tema: 500 px (mínim 40). L'alçada s'ajusta sola. Per un resultat nítid, " 459 "useu un fitxer de logo d'almenys aquesta amplada." 459 460 460 461 #: functions.php:1638 … … 533 534 534 535 #: functions.php:5316 535 msgid "Features (one per line)"536 msgstr "Característiques (una per línia)"536 msgid "Features, separated by |" 537 msgstr "Característiques, separades per |" 537 538 538 539 #: functions.php:4797 … … 867 868 868 869 #: functions.php:2286 869 msgid "Logo, site width, sidebar, header social links and header image." 870 msgstr "" 871 "Logotip, amplada del lloc, barra lateral, xarxes socials de la capçalera i " 872 "imatge de capçalera." 870 msgid "" 871 "Site width, sidebar, header social links and header image. The site logo is " 872 "set under Site Identity." 873 msgstr "" 874 "Amplada del lloc, barra lateral, xarxes socials de la capçalera i imatge de " 875 "capçalera. El logotip del lloc es configura a Identitat del lloc." 873 876 874 877 #: functions.php:3214 … … 931 934 #: functions.php:2376 932 935 msgid "" 933 "Mobile display width (screens ≤ 768 px). Theme maximum: 500 px (minimum 40)." 934 " Use the Customizer mobile preview to see it. For a sharp result, use a logo" 935 " file at least this wide." 936 msgstr "" 937 "Amplada de visualització al mòbil (pantalles ≤ 768 px). Màxim del tema: 500 " 938 "px (mínim 40). Useu la vista prèvia mòbil del Personalitzador per veure-ho. " 939 "Per un resultat nítid, useu un fitxer de logo d'almenys aquesta amplada." 936 "Mobile display width of the Site Logo (screens ≤ 768 px). Theme maximum: " 937 "500 px (minimum 40). Use the Customizer mobile preview to see it. For a " 938 "sharp result, use a logo file at least this wide." 939 msgstr "" 940 "Amplada de visualització del logotip del lloc al mòbil (pantalles ≤ 768 " 941 "px). Màxim del tema: 500 px (mínim 40). Useu la vista prèvia mòbil del " 942 "Personalitzador per veure-ho. Per un resultat nítid, useu un fitxer de logo " 943 "d'almenys aquesta amplada." 940 944 941 945 #: tsothm-mobile-menu.php:76 tsothm-mobile-menu.php:187 … … 1135 1139 #: functions.php:3548 1136 1140 msgid "" 1137 "Plans for the \"Pricing\" page template. If left empty, the page will show " 1138 "the block content (\"Pricing (3 plans)\" pattern)." 1139 msgstr "" 1140 "Plans per a la plantilla de pàgina «Precios». Si ho deixes buit, la pàgina " 1141 "mostrarà el contingut de blocs (patró «Precios (3 planes)»)." 1141 "Up to 5 plans for the \"Pricing\" page template. If left empty, the page " 1142 "shows the block content (\"Pricing (3 plans)\" pattern)." 1143 msgstr "" 1144 "Fins a 5 plans per a la plantilla de pàgina «Precios». Si ho deixes buit, la " 1145 "pàgina mostra el contingut de blocs (patró «Precios (3 planes)»)." 1146 1147 #: functions.php 1148 msgid "" 1149 "Maximum 5 plans. Separate features with a vertical bar, for example: " 1150 "Support | Updates | Backups." 1151 msgstr "" 1152 "Màxim 5 plans. Separa les característiques amb una barra vertical, per " 1153 "exemple: Suport | Actualitzacions | Còpies." 1142 1154 1143 1155 #: functions.php:1714 … … 1855 1867 "Família tipogràfica i estil del text de la barra de novetats / anuncis entre" 1856 1868 " la capçalera i el menú. Els colors són a Colors → Anunci." 1869 1870 #: style.css 1871 msgid "A classic blog theme with an orange frame and a white content area. The home page is a two-column post grid with live search and a Load more button. Posts use a right sidebar. The Customizer controls colors, typography, and the Site Logo, and includes a day and night mode. Page templates are included for contact, portfolio, pricing, team, and FAQ." 1872 msgstr "Tema de blog clàssic, amb marc taronja i àrea de contingut blanca. La portada és una graella de dues columnes, amb cerca en directe i un botó per carregar-ne més. Els articles tenen barra lateral dreta. El Personalitzador controla els colors, la tipografia i el logotip del lloc, i inclou un mode dia i nit. Hi ha plantilles de pàgina per a contacte, portafoli, preus, equip i preguntes freqüents." 1873 1874 #: functions.php 1875 msgid "Image viewer" 1876 msgstr "Visor d'imatges" 1877 1878 #: functions.php 1879 msgid "Close" 1880 msgstr "Tanca" 1881 1882 #: functions.php 1883 msgid "Previous image" 1884 msgstr "Imatge anterior" 1885 1886 #: functions.php 1887 msgid "Next image" 1888 msgstr "Imatge següent" -
tso-blog/1.0.9/languages/tso-blog-es_ES.po
r353345 r356198 453 453 #: functions.php:2352 454 454 msgid "" 455 "Desktop display width. Theme maximum: 500 px (minimum 40). Height adjusts " 456 "automatically. For a sharp result, use a logo file at least this wide." 457 msgstr "" 458 "Ancho de visualización en escritorio. Máximo del tema: 500 px (mínimo 40). " 459 "La altura se ajusta sola. Para un resultado nítido, use un archivo de logo " 460 "de al menos este ancho." 455 "Desktop display width of the Site Logo. Theme maximum: 500 px (minimum 40). " 456 "Height adjusts automatically. For a sharp result, use a logo file at least " 457 "this wide." 458 msgstr "" 459 "Ancho de visualización del logotipo del sitio en escritorio. Máximo del " 460 "tema: 500 px (mínimo 40). La altura se ajusta sola. Para un resultado " 461 "nítido, use un archivo de logo de al menos este ancho." 461 462 462 463 #: functions.php:1638 … … 535 536 536 537 #: functions.php:5316 537 msgid "Features (one per line)"538 msgstr "Características (una por línea)"538 msgid "Features, separated by |" 539 msgstr "Características, separadas por |" 539 540 540 541 #: functions.php:4797 … … 869 870 870 871 #: functions.php:2286 871 msgid "Logo, site width, sidebar, header social links and header image." 872 msgstr "" 873 "Logo, ancho del sitio, barra lateral, enlaces sociales de la cabecera e " 874 "imagen de cabecera." 872 msgid "" 873 "Site width, sidebar, header social links and header image. The site logo is " 874 "set under Site Identity." 875 msgstr "" 876 "Ancho del sitio, barra lateral, enlaces sociales de la cabecera e imagen de " 877 "cabecera. El logotipo del sitio se configura en Identidad del sitio." 875 878 876 879 #: functions.php:3214 … … 933 936 #: functions.php:2376 934 937 msgid "" 935 "Mobile display width (screens ≤ 768 px). Theme maximum: 500 px (minimum 40)." 936 " Use the Customizer mobile preview to see it. For a sharp result, use a logo" 937 " file at least this wide." 938 msgstr "" 939 "Ancho de visualización en móvil (pantallas ≤ 768 px). Máximo del tema: 500 " 940 "px (mínimo 40). Use la vista previa móvil del Personalizador para verlo. " 941 "Para un resultado nítido, use un archivo de logo de al menos este ancho." 938 "Mobile display width of the Site Logo (screens ≤ 768 px). Theme maximum: " 939 "500 px (minimum 40). Use the Customizer mobile preview to see it. For a " 940 "sharp result, use a logo file at least this wide." 941 msgstr "" 942 "Ancho de visualización del logotipo del sitio en móvil (pantallas ≤ 768 " 943 "px). Máximo del tema: 500 px (mínimo 40). Use la vista previa móvil del " 944 "Personalizador para verlo. Para un resultado nítido, use un archivo de logo " 945 "de al menos este ancho." 942 946 943 947 #: tsothm-mobile-menu.php:76 tsothm-mobile-menu.php:187 … … 1139 1143 #: functions.php:3548 1140 1144 msgid "" 1141 "Plans for the \"Pricing\" page template. If left empty, the page will show " 1142 "the block content (\"Pricing (3 plans)\" pattern)." 1143 msgstr "" 1144 "Planes para la plantilla de página «Precios». Si lo dejas vacío, la página " 1145 "mostrará el contenido de bloques (patrón «Precios (3 planes)»)." 1145 "Up to 5 plans for the \"Pricing\" page template. If left empty, the page " 1146 "shows the block content (\"Pricing (3 plans)\" pattern)." 1147 msgstr "" 1148 "Hasta 5 planes para la plantilla de página «Precios». Si lo dejas vacío, la " 1149 "página muestra el contenido de bloques (patrón «Precios (3 planes)»)." 1150 1151 #: functions.php 1152 msgid "" 1153 "Maximum 5 plans. Separate features with a vertical bar, for example: " 1154 "Support | Updates | Backups." 1155 msgstr "" 1156 "Máximo 5 planes. Separa las características con una barra vertical, por " 1157 "ejemplo: Soporte | Actualizaciones | Copias." 1146 1158 1147 1159 #: functions.php:1714 … … 1863 1875 "Familia tipográfica y estilo del texto de la barra de novedades / anuncios " 1864 1876 "entre la cabecera y el menú. Los colores están en Colores → Anuncio." 1877 1878 #: style.css 1879 msgid "A classic blog theme with an orange frame and a white content area. The home page is a two-column post grid with live search and a Load more button. Posts use a right sidebar. The Customizer controls colors, typography, and the Site Logo, and includes a day and night mode. Page templates are included for contact, portfolio, pricing, team, and FAQ." 1880 msgstr "Tema de blog clásico, con marco naranja y área de contenido blanca. La portada es una cuadrícula de dos columnas, con búsqueda en directo y un botón para cargar más. Los artículos llevan barra lateral derecha. El Personalizador controla los colores, la tipografía y el logotipo del sitio, e incluye un modo día y noche. Hay plantillas de página para contacto, portafolio, precios, equipo y preguntas frecuentes." 1881 1882 #: functions.php 1883 msgid "Image viewer" 1884 msgstr "Visor de imágenes" 1885 1886 #: functions.php 1887 msgid "Close" 1888 msgstr "Cerrar" 1889 1890 #: functions.php 1891 msgid "Previous image" 1892 msgstr "Imagen anterior" 1893 1894 #: functions.php 1895 msgid "Next image" 1896 msgstr "Imagen siguiente" -
tso-blog/1.0.9/readme.txt
r353346 r356198 5 5 Tested up to: 7.1 6 6 Requires PHP: 7.4 7 Stable tag: 1.0. 87 Stable tag: 1.0.9 8 8 License: GNU General Public License v2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Classic blog theme with a n orange frame and a white content area. Includes a two-column home grid with Load more, live search, a day/night color mode, Customizer options for colors, typography and logo, announcement bars, ready-made page templates (portfolio, pricing, team, FAQ, contact and more) and optional Google Fonts.11 Classic blog theme with a two-column grid, live search, day and night mode, and page templates. 12 12 13 13 == Description == … … 50 50 = How do I change the logo size? = 51 51 52 Appearance → Customize → Logo. Upload the image and set desktop and mobile max widths. Height scales automatically.52 Appearance → Customize → Site Identity. Upload the image with the WordPress Site Logo control, then set the desktop and mobile display widths in the same section. Height scales automatically. The theme does not add a second logo uploader. 53 53 54 54 = How do I make the site wider? = … … 143 143 144 144 == Changelog == 145 146 = 1.0.9 = 147 * Languages: keep bundled Catalan and Spanish only (tso-blog-ca, tso-blog-es_ES). English is the source text, so no en_US catalog. 148 * i18n: main menu label and lightbox controls use gettext. Script fallbacks are English. 149 * Announcement: the enter animation no longer plays on every page or refresh. It runs only when rotation changes to the next notice. 150 * Description rewritten to match the current theme. The readme summary stays within 150 characters. 151 * Tags checked against the WordPress.org list. All current tags are allowed. Only subject tags are limited to three; this theme uses one: blog. 152 * Theme review: the core Site Logo control stays in Site Identity. Logo width settings sit next to it. Removed the separate Logo section and the bundled logo-file fallback. 153 * Theme review: at most three Customizer textareas (footer legal text, contact intro, contact address). The Maps embed and repeater notes are single-line fields. 154 * Theme review: the pricing plans repeater accepts at most 5 plans. 155 * Theme review: screenshot.png is original theme artwork. License and source are listed under Resources. 145 156 146 157 = 1.0.8 = … … 232 243 * Dashicons (Customizer social order handle), Copyright WordPress contributors, GNU GPL v2 or later 233 244 * Google Fonts (optional remote), Copyright respective font authors, SIL Open Font License / Apache 2.0 as declared by each family on fonts.google.com 245 246 * Screenshot (screenshot.png) 247 Copyright: 2026 Tu Soporte Online 248 License: GNU General Public License v2 or later 249 License URI: https://www.gnu.org/licenses/gpl-2.0.html 250 Source: original artwork created for this theme (orange frame, header, menu and post cards with solid-color placeholders). It does not include third-party photographs, illustrations or logos, so there is no external image URL. -
tso-blog/1.0.9/style.css
r353346 r356198 3 3 Author: deadko 4 4 Author URI: https://tusoporteonline.es 5 Description: Classic blog theme with an orange frame and a white content area. Includes a two-column home grid with Load more, live search, a day/night color mode, Customizer options for colors, typography and logo, announcement bars, ready-made page templates (portfolio, pricing, team, FAQ, contact and more) and optional Google Fonts.6 Version: 1.0. 85 Description: A classic blog theme with an orange frame and a white content area. The home page is a two-column post grid with live search and a Load more button. Posts use a right sidebar. The Customizer controls colors, typography, and the Site Logo, and includes a day and night mode. Page templates are included for contact, portfolio, pricing, team, and FAQ. 6 Version: 1.0.9 7 7 Requires at least: 6.1 8 8 Tested up to: 7.1 … … 747 747 } 748 748 749 .tsothm-announcement--slide .tsothm-announcement-slide.is-active.is-instant, 750 .tsothm-announcement--fade .tsothm-announcement-slide.is-active.is-instant, 751 .tsothm-announcement--rise .tsothm-announcement-slide.is-active.is-instant { 752 -webkit-transition: none; 753 transition: none; 754 -webkit-transform: none; 755 transform: none; 756 opacity: 1; 757 } 758 749 759 .tsothm-announcement--slide .tsothm-announcement-slide.is-leaving { 750 760 -webkit-transform: translateX(-100%); -
tso-blog/1.0.9/tso-customize-repeater.js
r351940 r356198 26 26 html += '<div class="tso-repeater-image">'; 27 27 html += '<div class="tso-repeater-image-preview"></div>'; 28 html += '<button type="button" class="button tso-repeater-image-select">' + ( window.tsoRepeaterL10n && window.tsoRepeaterL10n.selectImage ? window.tsoRepeaterL10n.selectImage : 'Selec cionar imagen' ) + '</button> ';29 html += '<button type="button" class="button-link tso-repeater-image-remove">' + ( window.tsoRepeaterL10n && window.tsoRepeaterL10n.removeImage ? window.tsoRepeaterL10n.removeImage : ' Quitar' ) + '</button>';28 html += '<button type="button" class="button tso-repeater-image-select">' + ( window.tsoRepeaterL10n && window.tsoRepeaterL10n.selectImage ? window.tsoRepeaterL10n.selectImage : 'Select image' ) + '</button> '; 29 html += '<button type="button" class="button-link tso-repeater-image-remove">' + ( window.tsoRepeaterL10n && window.tsoRepeaterL10n.removeImage ? window.tsoRepeaterL10n.removeImage : 'Remove' ) + '</button>'; 30 30 html += '<input type="hidden" data-field="' + escAttr( key ) + '" value="' + escAttr( value || 0 ) + '" />'; 31 31 html += '</div>'; … … 76 76 77 77 var fields = $el.data( 'fields' ) || []; 78 var maxItems = parseInt( $el.attr( 'data-max' ), 10 ); 79 if ( ! maxItems || maxItems < 1 ) { 80 maxItems = 50; 81 } 78 82 var $input = $el.find( '.tso-repeater-input' ); 79 83 var $list = $el.find( '.tso-repeater-list' ); 84 var $add = $el.find( '.tso-repeater-add' ); 80 85 var rows = []; 86 var rawRows = $input.val() || '[]'; 87 var settingId = $input.attr( 'data-customize-setting-link' ); 88 if ( settingId && wp.customize && wp.customize( settingId ) ) { 89 rawRows = wp.customize( settingId ).get(); 90 } 81 91 try { 82 rows = JSON.parse( $input.val()|| '[]' );92 rows = JSON.parse( rawRows || '[]' ); 83 93 } catch ( e ) { 84 94 rows = []; … … 111 121 } 112 122 123 function updateAddButton() { 124 $add.prop( 'disabled', $list.children( '.tso-repeater-row' ).length >= maxItems ); 125 } 126 113 127 function addRow( row ) { 128 if ( $list.children( '.tso-repeater-row' ).length >= maxItems ) { 129 return; 130 } 114 131 row = row || {}; 115 132 var $row = $( buildRowHtml( fields, row ) ); … … 120 137 } 121 138 } ); 122 } 123 124 rows.forEach( addRow ); 139 updateAddButton(); 140 } 141 142 rows.slice( 0, maxItems ).forEach( addRow ); 143 if ( rows.length > maxItems ) { 144 sync(); 145 } 146 updateAddButton(); 125 147 126 148 $list.sortable( { … … 133 155 $el.on( 'click', '.tso-repeater-add', function ( e ) { 134 156 e.preventDefault(); 157 if ( $list.children( '.tso-repeater-row' ).length >= maxItems ) { 158 return; 159 } 135 160 addRow( {} ); 136 161 sync(); … … 141 166 $( this ).closest( '.tso-repeater-row' ).remove(); 142 167 sync(); 168 updateAddButton(); 143 169 } ); 144 170 … … 155 181 156 182 var frame = wp.media( { 157 title: window.tsoRepeaterL10n ? window.tsoRepeaterL10n.chooseImage : ' Elegir imagen',183 title: window.tsoRepeaterL10n ? window.tsoRepeaterL10n.chooseImage : 'Choose image', 158 184 multiple: false, 159 185 library: { type: 'image' }, -
tso-blog/1.0.9/tso-lightbox.js
r351940 r356198 61 61 overlay.setAttribute('role', 'dialog'); 62 62 overlay.setAttribute('aria-modal', 'true'); 63 overlay.setAttribute('aria-label', 'Visor de imágenes'); 63 var lbI18n = window.tsothmLightbox || {}; 64 overlay.setAttribute('aria-label', lbI18n.viewer || 'Image viewer'); 64 65 65 66 var imgEl = document.createElement('img'); … … 69 70 var btnClose = document.createElement('button'); 70 71 btnClose.id = 'tso-lb-close'; 71 btnClose.setAttribute('aria-label', 'Cerrar');72 btnClose.setAttribute('aria-label', lbI18n.close || 'Close'); 72 73 btnClose.innerHTML = '✕'; 73 74 74 75 var btnPrev = document.createElement('button'); 75 76 btnPrev.id = 'tso-lb-prev'; 76 btnPrev.setAttribute('aria-label', 'Imagen anterior');77 btnPrev.setAttribute('aria-label', lbI18n.prev || 'Previous image'); 77 78 btnPrev.innerHTML = '❮'; 78 79 79 80 var btnNext = document.createElement('button'); 80 81 btnNext.id = 'tso-lb-next'; 81 btnNext.setAttribute('aria-label', 'Imagen siguiente');82 btnNext.setAttribute('aria-label', lbI18n.next || 'Next image'); 82 83 btnNext.innerHTML = '❯'; 83 84 -
tso-blog/1.0.9/tso-live-search.js
r351020 r356198 9 9 var cacheKey = ( window.tsothmSearch && window.tsothmSearch.loadMoreCacheKey ) || 'tsothm_loadmore_state'; 10 10 var i18n = ( window.tsothmSearch && window.tsothmSearch.i18n ) || {}; 11 var msgSearching = i18n.searching || ' Buscando…';12 var msgNoResults = i18n.noResults || 'No se encontraron artículos.';11 var msgSearching = i18n.searching || 'Searching…'; 12 var msgNoResults = i18n.noResults || 'No posts found.'; 13 13 var instances = []; 14 14 -
tso-blog/1.0.9/tso-load-more.js
r351020 r356198 9 9 var container = document.getElementById( 'posts-container' ); 10 10 var CACHE_KEY = cfg.cacheKey || 'tsothm_loadmore_state'; 11 var loadText = cfg.loadText || ' Cargar más';12 var loadingText = cfg.loadingText || ' Cargando...';11 var loadText = cfg.loadText || 'Load more'; 12 var loadingText = cfg.loadingText || 'Loading...'; 13 13 14 14 if ( ! container ) { -
tso-blog/1.0.9/tsothm-announcement.js
r353345 r356198 45 45 var timer = null; 46 46 var animating = false; 47 var nextAt = 0; 47 48 // Keep in sync with the slowest CSS transition (~1.35s + buffer). 48 49 var animMs = reduceMotion ? 0 : 1500; 50 var storageKey = 'tsothmAnnounceSchedule'; 51 52 function scheduleSignature() { 53 return [ 54 root.getAttribute( 'data-effect' ) || '', 55 String( intervalSec ), 56 String( slides.length ) 57 ].join( '|' ); 58 } 59 60 function readSchedule() { 61 try { 62 var data = JSON.parse( window.sessionStorage.getItem( storageKey ) || '' ); 63 if ( ! data || data.sig !== scheduleSignature() ) { 64 return null; 65 } 66 if ( typeof data.index !== 'number' || typeof data.nextAt !== 'number' ) { 67 return null; 68 } 69 if ( data.index < 0 || data.index >= slides.length ) { 70 return null; 71 } 72 return data; 73 } catch ( e ) { 74 return null; 75 } 76 } 77 78 function writeSchedule( slideIndex, dueAt ) { 79 try { 80 window.sessionStorage.setItem( storageKey, JSON.stringify( { 81 sig: scheduleSignature(), 82 index: slideIndex, 83 nextAt: dueAt 84 } ) ); 85 } catch ( e ) {} 86 } 49 87 50 88 function clearSlideState( slide ) { 51 slide.classList.remove( 'is-active', 'is-entering', 'is-leaving' );89 slide.classList.remove( 'is-active', 'is-entering', 'is-leaving', 'is-instant' ); 52 90 } 53 91 … … 64 102 } 65 103 104 function showSettled( slideIndex ) { 105 slides.forEach( clearSlideState ); 106 slides[ slideIndex ].classList.add( 'is-active', 'is-instant' ); 107 index = slideIndex; 108 } 109 66 110 function show( nextIndex ) { 67 111 if ( animating || nextIndex === index || ! slides[ nextIndex ] ) { 68 return ;112 return false; 69 113 } 70 114 animating = true; … … 72 116 var next = slides[ nextIndex ]; 73 117 74 current.classList.remove( 'is-active', 'is-entering' );118 current.classList.remove( 'is-active', 'is-entering', 'is-instant' ); 75 119 current.classList.add( 'is-leaving' ); 76 120 … … 78 122 79 123 window.setTimeout( function () { 80 current.classList.remove( 'is-leaving' );124 current.classList.remove( 'is-leaving', 'is-instant' ); 81 125 index = nextIndex; 82 126 animating = false; 83 127 }, animMs ); 84 } 85 86 function next() { 87 show( ( index + 1 ) % slides.length ); 88 } 89 90 function startTimer() { 128 return true; 129 } 130 131 function queueNext() { 91 132 if ( ! rotate || timer ) { 92 133 return; 93 134 } 94 timer = window.setInterval( next, intervalSec * 1000 ); 135 var wait = Math.max( 0, nextAt - Date.now() ); 136 timer = window.setTimeout( function () { 137 timer = null; 138 var dest = ( index + 1 ) % slides.length; 139 if ( ! show( dest ) ) { 140 window.setTimeout( queueNext, Math.max( animMs, 50 ) ); 141 return; 142 } 143 nextAt = Date.now() + intervalSec * 1000; 144 writeSchedule( dest, nextAt ); 145 queueNext(); 146 }, wait ); 95 147 } 96 148 97 149 function stopTimer() { 98 150 if ( timer ) { 99 window.clear Interval( timer );151 window.clearTimeout( timer ); 100 152 timer = null; 101 153 } … … 109 161 stopTimer(); 110 162 } else { 111 startTimer(); 112 } 113 } 114 115 slides.forEach( function ( slide, i ) { 116 clearSlideState( slide ); 117 if ( 0 === i ) { 118 if ( reduceMotion ) { 119 slide.classList.add( 'is-active' ); 120 } else { 121 playEnter( slide ); 122 } 123 } 124 } ); 163 queueNext(); 164 } 165 } 166 167 slides.forEach( clearSlideState ); 125 168 126 169 if ( rotate ) { 127 startTimer(); 170 var now = Date.now(); 171 var saved = readSchedule(); 172 var period = intervalSec * 1000; 173 if ( saved && now < saved.nextAt ) { 174 index = saved.index; 175 nextAt = saved.nextAt; 176 } else if ( saved ) { 177 var steps = Math.floor( ( now - saved.nextAt ) / period ) + 1; 178 index = ( saved.index + steps ) % slides.length; 179 var overdue = ( now - saved.nextAt ) % period; 180 nextAt = now + ( overdue ? period - overdue : period ); 181 } else { 182 index = 0; 183 nextAt = now + period; 184 } 185 showSettled( index ); 186 writeSchedule( index, nextAt ); 187 queueNext(); 188 } else { 189 showSettled( 0 ); 128 190 } 129 191
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)