Changeset 3472434
- Timestamp:
- 03/02/2026 07:55:00 AM (less than one hour ago)
- Location:
- ai-discovery-files
- Files:
-
- 2 added
- 22 edited
- 1 copied
-
tags/1.1.0 (copied) (copied from ai-discovery-files/trunk)
-
tags/1.1.0/admin/class-admin.php (modified) (3 diffs)
-
tags/1.1.0/admin/class-settings.php (modified) (1 diff)
-
tags/1.1.0/admin/css/admin.css (modified) (3 diffs)
-
tags/1.1.0/admin/js/admin.js (modified) (1 diff)
-
tags/1.1.0/admin/views/partials/directory-cta.php (modified) (2 diffs)
-
tags/1.1.0/admin/views/partials/verify-modal.php (added)
-
tags/1.1.0/admin/views/settings-page.php (modified) (2 diffs)
-
tags/1.1.0/admin/views/tab-status.php (modified) (2 diffs)
-
tags/1.1.0/ai-discovery-files.php (modified) (2 diffs)
-
tags/1.1.0/includes/class-plugin.php (modified) (1 diff)
-
tags/1.1.0/includes/class-server.php (modified) (2 diffs)
-
tags/1.1.0/readme.txt (modified) (3 diffs)
-
trunk/admin/class-admin.php (modified) (3 diffs)
-
trunk/admin/class-settings.php (modified) (1 diff)
-
trunk/admin/css/admin.css (modified) (3 diffs)
-
trunk/admin/js/admin.js (modified) (1 diff)
-
trunk/admin/views/partials/directory-cta.php (modified) (2 diffs)
-
trunk/admin/views/partials/verify-modal.php (added)
-
trunk/admin/views/settings-page.php (modified) (2 diffs)
-
trunk/admin/views/tab-status.php (modified) (2 diffs)
-
trunk/ai-discovery-files.php (modified) (2 diffs)
-
trunk/includes/class-plugin.php (modified) (1 diff)
-
trunk/includes/class-server.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ai-discovery-files/tags/1.1.0/admin/class-admin.php
r3472044 r3472434 36 36 add_action( 'wp_ajax_aidf_validate_files', array( __CLASS__, 'ajax_validate_files' ) ); 37 37 add_action( 'wp_ajax_aidf_dismiss_welcome', array( __CLASS__, 'ajax_dismiss_welcome' ) ); 38 add_action( 'wp_ajax_aidf_save_verify_code', array( __CLASS__, 'ajax_save_verify_code' ) ); 38 39 add_action( 'admin_notices', array( __CLASS__, 'maybe_show_welcome_notice' ) ); 39 40 add_action( 'admin_notices', array( __CLASS__, 'maybe_show_conflict_notice' ) ); … … 114 115 'unknownError' => __( 'Unknown error', 'ai-discovery-files' ), 115 116 'crossFileConsistency' => __( 'Cross-File Consistency', 'ai-discovery-files' ), 117 'verifyFileActive' => __( 'Verification file is live at', 'ai-discovery-files' ), 118 'verifyFileInactive' => __( 'No verification code set. Enter your code above to activate.', 'ai-discovery-files' ), 116 119 ), 117 120 ) … … 226 229 227 230 wp_send_json_success( $results ); 231 } 232 233 /** 234 * AJAX handler: save domain verification code. 235 * 236 * @return void 237 */ 238 public static function ajax_save_verify_code() { 239 check_ajax_referer( 'aidf_admin_nonce', 'nonce' ); 240 241 if ( ! current_user_can( 'manage_options' ) ) { 242 wp_send_json_error( __( 'Permission denied.', 'ai-discovery-files' ) ); 243 } 244 245 $code = isset( $_POST['verify_code'] ) ? sanitize_text_field( wp_unslash( $_POST['verify_code'] ) ) : ''; 246 247 // Validate: must match "ai-visibility-verify=" followed by hex, or empty to clear. 248 if ( '' !== $code && ! preg_match( '/^ai-visibility-verify=[a-f0-9]+$/i', $code ) ) { 249 wp_send_json_error( __( 'Invalid verification code. The code should be in the format: ai-visibility-verify=abc123', 'ai-discovery-files' ) ); 250 } 251 252 $settings = get_option( 'aidf_settings', array() ); 253 $settings['verify_code'] = $code; 254 update_option( 'aidf_settings', $settings ); 255 256 // Flush rewrite rules to ensure the verify file route is active. 257 AIDF_Server::register_rewrite_rules(); 258 flush_rewrite_rules(); 259 260 $data = array( 261 'message' => empty( $code ) 262 ? __( 'Verification code removed.', 'ai-discovery-files' ) 263 : __( 'Verification code saved.', 'ai-discovery-files' ), 264 'active' => ! empty( $code ), 265 'url' => home_url( '/ai-visibility-verify.txt' ), 266 ); 267 268 wp_send_json_success( $data ); 228 269 } 229 270 -
ai-discovery-files/tags/1.1.0/admin/class-settings.php
r3472044 r3472434 270 270 } 271 271 272 // Directory verification code — "ai-visibility-verify=" followed by hex. 273 if ( isset( $input['verify_code'] ) ) { 274 $code = sanitize_text_field( $input['verify_code'] ); 275 $clean['verify_code'] = ( '' === $code || preg_match( '/^ai-visibility-verify=[a-f0-9]+$/i', $code ) ) ? $code : $fallback['verify_code']; 276 } else { 277 $clean['verify_code'] = isset( $fallback['verify_code'] ) ? $fallback['verify_code'] : ''; 278 } 279 272 280 // Flush rewrite rules since active files may have changed. 273 281 AIDF_Server::register_rewrite_rules(); -
ai-discovery-files/tags/1.1.0/admin/css/admin.css
r3472044 r3472434 1865 1865 } 1866 1866 1867 /* -------------------------------------------------------- 1868 23. Domain Verification Modal 1869 -------------------------------------------------------- */ 1870 1871 /* Backdrop */ 1872 .aidf-verify-modal { 1873 position: fixed; 1874 inset: 0; 1875 z-index: 100100; 1876 display: flex; 1877 align-items: center; 1878 justify-content: center; 1879 padding: var(--aidf-sp-5); 1880 animation: aidfModalFadeIn 0.2s ease-out; 1881 } 1882 1883 .aidf-verify-modal__backdrop { 1884 position: absolute; 1885 inset: 0; 1886 background: rgba(0, 0, 0, 0.6); 1887 backdrop-filter: blur(4px); 1888 -webkit-backdrop-filter: blur(4px); 1889 } 1890 1891 /* Card */ 1892 .aidf-verify-modal__card { 1893 position: relative; 1894 width: 100%; 1895 max-width: 580px; 1896 background: var(--aidf-white); 1897 border-radius: var(--aidf-radius-lg); 1898 box-shadow: 0 24px 80px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.05); 1899 overflow: hidden; 1900 animation: aidfModalSlideUp 0.25s ease-out; 1901 } 1902 1903 /* Header */ 1904 .aidf-verify-modal__header { 1905 display: flex; 1906 align-items: center; 1907 justify-content: space-between; 1908 padding: var(--aidf-sp-5) var(--aidf-sp-6); 1909 background: linear-gradient(135deg, var(--aidf-dark) 0%, var(--aidf-dark-mid) 100%); 1910 color: var(--aidf-text-inverse); 1911 } 1912 1913 .aidf-verify-modal__header-content { 1914 display: flex; 1915 align-items: center; 1916 gap: var(--aidf-sp-3); 1917 } 1918 1919 .aidf-verify-modal__header-icon { 1920 display: flex; 1921 align-items: center; 1922 justify-content: center; 1923 width: 44px; 1924 height: 44px; 1925 background: linear-gradient(135deg, var(--aidf-orange) 0%, #ff9d42 100%); 1926 border-radius: 10px; 1927 flex-shrink: 0; 1928 } 1929 1930 .aidf-verify-modal__header-icon .dashicons { 1931 width: 22px; 1932 height: 22px; 1933 font-size: 22px; 1934 color: var(--aidf-dark); 1935 } 1936 1937 .aidf-verify-modal__title { 1938 font-size: 18px; 1939 font-weight: 700; 1940 color: var(--aidf-text-inverse); 1941 letter-spacing: -0.01em; 1942 line-height: 1.3; 1943 } 1944 1945 .aidf-verify-modal__subtitle { 1946 margin: 2px 0 0; 1947 font-size: 12px; 1948 color: rgba(255, 255, 255, 0.6); 1949 font-weight: 500; 1950 text-transform: uppercase; 1951 letter-spacing: 0.04em; 1952 } 1953 1954 .aidf-verify-modal__close { 1955 display: flex; 1956 align-items: center; 1957 justify-content: center; 1958 width: 32px; 1959 height: 32px; 1960 background: rgba(255, 255, 255, 0.1); 1961 border: none; 1962 border-radius: 6px; 1963 cursor: pointer; 1964 color: rgba(255, 255, 255, 0.7); 1965 transition: all 0.15s ease; 1966 } 1967 1968 .aidf-verify-modal__close:hover { 1969 background: rgba(255, 255, 255, 0.2); 1970 color: var(--aidf-text-inverse); 1971 } 1972 1973 .aidf-verify-modal__close .dashicons { 1974 width: 20px; 1975 height: 20px; 1976 font-size: 20px; 1977 } 1978 1979 /* Body */ 1980 .aidf-verify-modal__body { 1981 padding: var(--aidf-sp-6); 1982 } 1983 1984 .aidf-verify-modal__intro { 1985 margin-bottom: var(--aidf-sp-5); 1986 } 1987 1988 .aidf-verify-modal__intro p { 1989 margin: 0 0 var(--aidf-sp-2) 0; 1990 font-size: var(--aidf-text-sm); 1991 color: var(--aidf-text-secondary); 1992 line-height: 1.6; 1993 } 1994 1995 .aidf-verify-modal__intro p:last-child { 1996 margin-bottom: 0; 1997 } 1998 1999 /* Steps */ 2000 .aidf-verify-modal__steps { 2001 display: flex; 2002 flex-direction: column; 2003 gap: var(--aidf-sp-3); 2004 margin-bottom: var(--aidf-sp-5); 2005 padding: var(--aidf-sp-4); 2006 background: var(--aidf-bg); 2007 border-radius: var(--aidf-radius); 2008 border: 1px solid var(--aidf-border-light); 2009 } 2010 2011 .aidf-verify-modal__step { 2012 display: flex; 2013 align-items: center; 2014 gap: var(--aidf-sp-3); 2015 } 2016 2017 .aidf-verify-modal__step-number { 2018 display: flex; 2019 align-items: center; 2020 justify-content: center; 2021 width: 24px; 2022 height: 24px; 2023 background: var(--aidf-orange); 2024 color: var(--aidf-text-on-orange); 2025 border-radius: 50%; 2026 font-size: 12px; 2027 font-weight: 700; 2028 flex-shrink: 0; 2029 line-height: 1; 2030 } 2031 2032 .aidf-verify-modal__step-text { 2033 font-size: var(--aidf-text-sm); 2034 color: var(--aidf-text); 2035 line-height: 1.4; 2036 } 2037 2038 .aidf-verify-modal__step-text a { 2039 color: var(--aidf-orange); 2040 font-weight: 600; 2041 text-decoration: none; 2042 } 2043 2044 .aidf-verify-modal__step-text a:hover { 2045 color: var(--aidf-orange-hover); 2046 text-decoration: underline; 2047 } 2048 2049 /* Code input */ 2050 .aidf-verify-modal__field { 2051 margin-bottom: var(--aidf-sp-4); 2052 } 2053 2054 .aidf-verify-modal__label { 2055 display: block; 2056 margin-bottom: var(--aidf-sp-2); 2057 font-size: var(--aidf-text-sm); 2058 font-weight: 600; 2059 color: var(--aidf-text); 2060 } 2061 2062 .aidf-verify-modal__input { 2063 width: 100%; 2064 padding: 10px 14px; 2065 font-size: 14px; 2066 font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; 2067 letter-spacing: 0.02em; 2068 color: var(--aidf-text); 2069 background: var(--aidf-white); 2070 border: 1px solid var(--aidf-border); 2071 border-radius: var(--aidf-radius); 2072 outline: none; 2073 transition: border-color 0.15s ease, box-shadow 0.15s ease; 2074 box-sizing: border-box; 2075 } 2076 2077 .aidf-verify-modal__input:focus { 2078 border-color: var(--aidf-orange); 2079 box-shadow: 0 0 0 3px var(--aidf-orange-glow); 2080 } 2081 2082 .aidf-verify-modal__input::placeholder { 2083 color: var(--aidf-text-tertiary); 2084 font-family: var(--aidf-font); 2085 letter-spacing: normal; 2086 } 2087 2088 /* Status */ 2089 .aidf-verify-modal__status { 2090 display: flex; 2091 align-items: center; 2092 gap: var(--aidf-sp-2); 2093 padding: var(--aidf-sp-3) var(--aidf-sp-4); 2094 border-radius: var(--aidf-radius); 2095 font-size: var(--aidf-text-sm); 2096 color: var(--aidf-text-secondary); 2097 background: var(--aidf-bg); 2098 border: 1px solid var(--aidf-border-light); 2099 } 2100 2101 .aidf-verify-modal__status .dashicons { 2102 width: 18px; 2103 height: 18px; 2104 font-size: 18px; 2105 flex-shrink: 0; 2106 } 2107 2108 .aidf-verify-modal__status--active { 2109 background: var(--aidf-green-bg); 2110 border-color: var(--aidf-green-border); 2111 color: #15803d; 2112 } 2113 2114 .aidf-verify-modal__status--active .dashicons { 2115 color: var(--aidf-green); 2116 } 2117 2118 .aidf-verify-modal__status a { 2119 color: var(--aidf-orange); 2120 font-weight: 500; 2121 word-break: break-all; 2122 } 2123 2124 /* Footer */ 2125 .aidf-verify-modal__footer { 2126 display: flex; 2127 align-items: center; 2128 justify-content: space-between; 2129 padding: var(--aidf-sp-4) var(--aidf-sp-6); 2130 background: var(--aidf-bg); 2131 border-top: 1px solid var(--aidf-border-light); 2132 } 2133 2134 .aidf-verify-modal__footer-right { 2135 display: flex; 2136 gap: var(--aidf-sp-2); 2137 } 2138 2139 .aidf-verify-modal__dashboard-link { 2140 display: inline-flex; 2141 align-items: center; 2142 gap: 4px; 2143 font-size: var(--aidf-text-sm); 2144 color: var(--aidf-text-secondary); 2145 text-decoration: none; 2146 transition: color 0.15s ease; 2147 } 2148 2149 .aidf-verify-modal__dashboard-link:hover { 2150 color: var(--aidf-orange); 2151 } 2152 2153 .aidf-verify-modal__dashboard-link .dashicons { 2154 width: 14px; 2155 height: 14px; 2156 font-size: 14px; 2157 } 2158 2159 .aidf-verify-modal__footer .aidf-btn .dashicons { 2160 width: 16px; 2161 height: 16px; 2162 font-size: 16px; 2163 margin-right: 2px; 2164 } 2165 2166 /* Animations */ 2167 @keyframes aidfModalFadeIn { 2168 from { opacity: 0; } 2169 to { opacity: 1; } 2170 } 2171 2172 @keyframes aidfModalSlideUp { 2173 from { opacity: 0; transform: translateY(12px) scale(0.98); } 2174 to { opacity: 1; transform: translateY(0) scale(1); } 2175 } 2176 2177 /* -------------------------------------------------------- 2178 23b. CTA Verify Button Variant 2179 -------------------------------------------------------- */ 2180 .aidf-directory-cta__actions { 2181 display: flex; 2182 gap: var(--aidf-sp-2); 2183 flex-shrink: 0; 2184 } 2185 2186 .aidf-directory-cta__button--verify { 2187 background: transparent; 2188 border: 2px solid rgba(255, 255, 255, 0.5); 2189 color: var(--aidf-text-inverse); 2190 cursor: pointer; 2191 } 2192 2193 .aidf-directory-cta__button--verify:hover { 2194 background: rgba(255, 255, 255, 0.15); 2195 border-color: rgba(255, 255, 255, 0.8); 2196 color: var(--aidf-text-inverse) !important; 2197 transform: translateY(-1px); 2198 } 2199 2200 .aidf-directory-cta__button--verify .dashicons { 2201 width: 16px; 2202 height: 16px; 2203 font-size: 16px; 2204 } 2205 2206 /* -------------------------------------------------------- 2207 23c. Inline Verification Panel (Status Tab) 2208 -------------------------------------------------------- */ 2209 .aidf-verify-panel { 2210 margin-top: var(--aidf-sp-5); 2211 } 2212 2213 .aidf-verify-panel .aidf-panel-title .dashicons { 2214 margin-right: 6px; 2215 color: var(--aidf-orange); 2216 } 2217 2218 .aidf-verify-inline { 2219 display: flex; 2220 align-items: center; 2221 justify-content: space-between; 2222 gap: var(--aidf-sp-4); 2223 } 2224 2225 .aidf-verify-inline__status { 2226 display: flex; 2227 align-items: center; 2228 gap: var(--aidf-sp-2); 2229 font-size: var(--aidf-text-sm); 2230 } 2231 2232 .aidf-verify-inline__status--active { 2233 color: #15803d; 2234 } 2235 2236 .aidf-verify-inline__status--active .dashicons { 2237 color: var(--aidf-green); 2238 } 2239 2240 .aidf-verify-inline__status a { 2241 color: var(--aidf-orange); 2242 } 2243 2244 .aidf-verify-inline__description { 2245 margin: 0; 2246 font-size: var(--aidf-text-sm); 2247 color: var(--aidf-text-secondary); 2248 } 2249 2250 /* -------------------------------------------------------- 2251 24. Responsive 2252 -------------------------------------------------------- */ 2253 @media (max-width: 960px) { 2254 .aidf-header { 2255 padding: var(--aidf-sp-4) var(--aidf-sp-5); 2256 } 2257 2258 .aidf-tabs { 2259 padding: 0 var(--aidf-sp-4); 2260 overflow-x: auto; 2261 } 2262 2263 .aidf-content { 2264 padding: var(--aidf-sp-5); 2265 } 2266 2267 .aidf-file-grid { 2268 grid-template-columns: 1fr; 2269 } 2270 } 2271 1867 2272 @media (max-width: 782px) { 2273 .aidf-wrap { 2274 margin-left: -10px; 2275 } 2276 2277 .aidf-tabs { 2278 top: 46px; /* Mobile admin bar height */ 2279 } 2280 2281 .aidf-header-right { 2282 display: none; 2283 } 2284 2285 .aidf-header-version { 2286 display: none; 2287 } 2288 1868 2289 .aidf-directory-cta__content { 1869 2290 flex-direction: column; … … 1872 2293 } 1873 2294 2295 .aidf-directory-cta__actions { 2296 flex-direction: column; 2297 width: 100%; 2298 } 2299 1874 2300 .aidf-directory-cta__button { 1875 2301 width: 100%; 1876 2302 justify-content: center; 1877 2303 } 1878 } 1879 1880 /* -------------------------------------------------------- 1881 23. Responsive (formerly 22) 1882 -------------------------------------------------------- */ 1883 @media (max-width: 960px) { 1884 .aidf-header { 1885 padding: var(--aidf-sp-4) var(--aidf-sp-5); 2304 2305 .aidf-verify-modal__card { 2306 max-height: 90vh; 2307 overflow-y: auto; 1886 2308 } 1887 2309 1888 .aidf- tabs{1889 padding: 0 var(--aidf-sp-4);1890 overflow-x: auto;2310 .aidf-verify-modal__footer { 2311 flex-direction: column; 2312 gap: var(--aidf-sp-3); 1891 2313 } 1892 2314 1893 .aidf- content {1894 padding: var(--aidf-sp-5);2315 .aidf-verify-modal__footer-right { 2316 width: 100%; 1895 2317 } 1896 2318 1897 .aidf- file-grid{1898 grid-template-columns: 1fr;2319 .aidf-verify-modal__footer-right .aidf-btn { 2320 flex: 1; 1899 2321 } 1900 } 1901 1902 @media (max-width: 782px) { 1903 .aidf-wrap { 1904 margin-left: -10px; 2322 2323 .aidf-verify-inline { 2324 flex-direction: column; 2325 align-items: flex-start; 1905 2326 } 1906 1907 .aidf-tabs { 1908 top: 46px; /* Mobile admin bar height */ 1909 } 1910 1911 .aidf-header-right { 1912 display: none; 1913 } 1914 1915 .aidf-header-version { 1916 display: none; 1917 } 1918 } 1919 1920 /* -------------------------------------------------------- 1921 23. WordPress Admin Overrides 2327 } 2328 2329 /* -------------------------------------------------------- 2330 25. WordPress Admin Overrides 1922 2331 -------------------------------------------------------- */ 1923 2332 … … 1948 2357 1949 2358 /* -------------------------------------------------------- 1950 2 4. Welcome Notice (global WP admin)2359 26. Welcome Notice (global WP admin) 1951 2360 -------------------------------------------------------- */ 1952 2361 .aidf-welcome-notice { -
ai-discovery-files/tags/1.1.0/admin/js/admin.js
r3472044 r3472434 461 461 }); 462 462 463 /* ------------------------------------------------------- 464 Domain Verification Modal 465 ------------------------------------------------------- */ 466 var verifyModal = $('#aidf-verify-modal'); 467 468 function openVerifyModal() { 469 verifyModal.show(); 470 $('body').css('overflow', 'hidden'); 471 verifyModal.find('#aidf-verify-code').focus(); 472 } 473 474 function closeVerifyModal() { 475 verifyModal.hide(); 476 $('body').css('overflow', ''); 477 } 478 479 // Open from CTA button or Status tab panel button. 480 $(document).on('click', '#aidf-open-verify-cta, #aidf-open-verify-panel', function (e) { 481 e.preventDefault(); 482 openVerifyModal(); 483 }); 484 485 // Close: X button, backdrop, Cancel button. 486 verifyModal.on('click', '[data-aidf-close-modal]', function () { 487 closeVerifyModal(); 488 }); 489 490 // Close: Escape key. 491 $(document).on('keydown', function (e) { 492 if (e.key === 'Escape' && verifyModal.is(':visible')) { 493 closeVerifyModal(); 494 } 495 }); 496 497 // Save verification code via AJAX. 498 $('#aidf-verify-save').on('click', function () { 499 var $btn = $(this); 500 var code = $('#aidf-verify-code').val().trim(); 501 var $status = $('#aidf-verify-status'); 502 503 $btn.prop('disabled', true).find('.dashicons').removeClass('dashicons-yes').addClass('dashicons-update'); 504 505 $.post(aidfAdmin.ajaxUrl, { 506 action: 'aidf_save_verify_code', 507 nonce: aidfAdmin.nonce, 508 verify_code: code 509 }, function (response) { 510 $btn.prop('disabled', false).find('.dashicons').removeClass('dashicons-update').addClass('dashicons-yes'); 511 512 if (!response.success) { 513 $status 514 .removeClass('aidf-verify-modal__status--active') 515 .html('<span class="dashicons dashicons-warning"></span> <span>' + escAttr(response.data) + '</span>'); 516 return; 517 } 518 519 var data = response.data; 520 521 if (data.active) { 522 $status 523 .addClass('aidf-verify-modal__status--active') 524 .html( 525 '<span class="dashicons dashicons-yes-alt"></span> ' + 526 '<span>' + escAttr(aidfAdmin.i18n.verifyFileActive) + ' ' + 527 '<a href="' + escAttr(data.url) + '" target="_blank" rel="noopener">' + escAttr(data.url) + '</a></span>' 528 ); 529 } else { 530 $status 531 .removeClass('aidf-verify-modal__status--active') 532 .html('<span class="dashicons dashicons-info-outline"></span> <span>' + escAttr(aidfAdmin.i18n.verifyFileInactive) + '</span>'); 533 } 534 535 // Flash the save button green briefly. 536 $btn.addClass('aidf-btn--success'); 537 setTimeout(function () { 538 $btn.removeClass('aidf-btn--success'); 539 }, 1500); 540 }).fail(function () { 541 $btn.prop('disabled', false).find('.dashicons').removeClass('dashicons-update').addClass('dashicons-yes'); 542 }); 543 }); 544 463 545 }); // end DOM ready 464 546 -
ai-discovery-files/tags/1.1.0/admin/views/partials/directory-cta.php
r3472044 r3472434 46 46 </div> 47 47 48 <div class="aidf-directory-cta__action ">48 <div class="aidf-directory-cta__actions"> 49 49 <a href="https://www.ai-visibility.org.uk/submit/" 50 50 class="aidf-directory-cta__button" … … 54 54 <span class="dashicons dashicons-external"></span> 55 55 </a> 56 <button type="button" class="aidf-directory-cta__button aidf-directory-cta__button--verify" id="aidf-open-verify-cta"> 57 <span class="dashicons dashicons-shield-alt"></span> 58 <?php esc_html_e( 'Verify Domain', 'ai-discovery-files' ); ?> 59 </button> 56 60 </div> 57 61 </div> -
ai-discovery-files/tags/1.1.0/admin/views/settings-page.php
r3472044 r3472434 95 95 ?> 96 96 <input type="hidden" name="aidf_settings[spec_attribution]" value="<?php echo esc_attr( $settings['spec_attribution'] ? '1' : '0' ); ?>" class="aidf-hidden-attribution"> 97 <input type="hidden" name="aidf_settings[verify_code]" value="<?php echo esc_attr( isset( $settings['verify_code'] ) ? $settings['verify_code'] : '' ); ?>"> 97 98 <?php endif; ?> 98 99 … … 114 115 <?php endif; ?> 115 116 </div> 117 118 <?php include AIDF_PLUGIN_DIR . 'admin/views/partials/verify-modal.php'; ?> 116 119 </div> -
ai-discovery-files/tags/1.1.0/admin/views/tab-status.php
r3472044 r3472434 81 81 82 82 <input type="hidden" name="aidf_settings[spec_attribution]" value="<?php echo esc_attr( $settings['spec_attribution'] ? '1' : '0' ); ?>"> 83 <input type="hidden" name="aidf_settings[verify_code]" value="<?php echo esc_attr( isset( $settings['verify_code'] ) ? $settings['verify_code'] : '' ); ?>"> 83 84 84 85 <?php foreach ( $tiers as $tier_slug => $tier ) : ?> … … 175 176 </div> 176 177 </div> 178 179 <!-- Domain Verification --> 180 <?php 181 $verify_code = isset( $settings['verify_code'] ) ? $settings['verify_code'] : ''; 182 $verify_active = ! empty( $verify_code ); 183 ?> 184 <div class="aidf-panel aidf-verify-panel"> 185 <div class="aidf-panel-header"> 186 <div> 187 <h2 class="aidf-panel-title"> 188 <span class="dashicons dashicons-shield-alt"></span> 189 <?php esc_html_e( 'Directory Verification', 'ai-discovery-files' ); ?> 190 <?php if ( $verify_active ) : ?> 191 <span class="aidf-badge aidf-badge--essential"><?php esc_html_e( 'active', 'ai-discovery-files' ); ?></span> 192 <?php endif; ?> 193 </h2> 194 <p class="aidf-panel-subtitle"><?php esc_html_e( 'Prove domain ownership to manage your listing in the AI Visibility Directory.', 'ai-discovery-files' ); ?></p> 195 </div> 196 </div> 197 <div class="aidf-panel-body"> 198 <div class="aidf-verify-inline"> 199 <?php if ( $verify_active ) : ?> 200 <div class="aidf-verify-inline__status aidf-verify-inline__status--active"> 201 <span class="dashicons dashicons-yes-alt"></span> 202 <span> 203 <?php esc_html_e( 'Verification file is live at', 'ai-discovery-files' ); ?> 204 <a href="<?php echo esc_url( home_url( '/ai-visibility-verify.txt' ) ); ?>" target="_blank" rel="noopener"> 205 /ai-visibility-verify.txt ↗ 206 </a> 207 </span> 208 </div> 209 <?php else : ?> 210 <p class="aidf-verify-inline__description"> 211 <?php esc_html_e( 'After submitting your site to the directory, enter your verification code here so the plugin can serve the ownership file automatically.', 'ai-discovery-files' ); ?> 212 </p> 213 <?php endif; ?> 214 <button type="button" class="aidf-btn aidf-btn--secondary" id="aidf-open-verify-panel"> 215 <span class="dashicons dashicons-shield-alt"></span> 216 <?php 217 echo $verify_active 218 ? esc_html__( 'Update Verification Code', 'ai-discovery-files' ) 219 : esc_html__( 'Enter Verification Code', 'ai-discovery-files' ); 220 ?> 221 </button> 222 </div> 223 </div> 224 </div> -
ai-discovery-files/tags/1.1.0/ai-discovery-files.php
r3472087 r3472434 4 4 * Plugin URI: https://www.ai-visibility.org.uk/wordpress-plugin/ai-discovery-files/ 5 5 * Description: Improve your AI Visibility by generating AI Discovery Files so AI systems like ChatGPT, Claude, and Gemini can correctly discover, interpret, and cite your website. 6 * Version: 1. 0.06 * Version: 1.1.0 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 8.0 … … 24 24 * Plugin constants. 25 25 */ 26 define( 'AIDF_VERSION', '1. 0.0' );26 define( 'AIDF_VERSION', '1.1.0' ); 27 27 define( 'AIDF_PLUGIN_FILE', __FILE__ ); 28 28 define( 'AIDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); -
ai-discovery-files/tags/1.1.0/includes/class-plugin.php
r3472044 r3472434 123 123 'active_files' => array( 'llms-txt', 'ai-txt' ), 124 124 'spec_attribution' => false, 125 126 // Directory verification. 127 'verify_code' => '', 125 128 ); 126 129 -
ai-discovery-files/tags/1.1.0/includes/class-server.php
r3472044 r3472434 57 57 ); 58 58 } 59 60 // Domain verification file for AI Visibility Directory. 61 add_rewrite_rule( 62 '^ai-visibility-verify\.txt$', 63 'index.php?aidf_file=verify', 64 'top' 65 ); 59 66 } 60 67 … … 80 87 if ( empty( $file_slug ) ) { 81 88 return; 89 } 90 91 // Handle verification file separately (not an AI Discovery File). 92 if ( 'verify' === $file_slug ) { 93 $settings = AIDF_Plugin::get_settings(); 94 $verify_code = isset( $settings['verify_code'] ) ? $settings['verify_code'] : ''; 95 96 if ( empty( $verify_code ) ) { 97 status_header( 404 ); 98 nocache_headers(); 99 echo esc_html__( '404 — Verification file not configured.', 'ai-discovery-files' ); 100 exit; 101 } 102 103 status_header( 200 ); 104 header( 'Content-Type: text/plain; charset=utf-8' ); 105 header( 'Cache-Control: no-store' ); 106 header( 'X-Robots-Tag: noindex' ); 107 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Plain text output, validated on save. 108 echo $verify_code; 109 exit; 82 110 } 83 111 -
ai-discovery-files/tags/1.1.0/readme.txt
r3472165 r3472434 3 3 Tags: ai, llms.txt, ai visibility, seo, chatgpt 4 4 Requires at least: 6.2 5 Tested up to: 6.9 .15 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 1. 0.07 Stable tag: 1.1.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 120 120 == Changelog == 121 121 122 = 1.1.0 = 123 * Add domain verification for the AI Visibility Directory 124 * New verification modal with step-by-step instructions 125 * Serve ai-visibility-verify.txt with user-supplied code 126 * Verify Domain button in directory CTA banner 127 * Verification panel on Status tab 128 * AJAX save for verification code (no page reload) 129 122 130 = 1.0.0 = 123 131 * Initial release … … 133 141 == Upgrade Notice == 134 142 143 = 1.1.0 = 144 New: Domain verification for the AI Visibility Directory. Serve your verification file directly from WordPress — no FTP needed. 145 135 146 = 1.0.0 = 136 147 Initial release. Install and configure your AI Discovery Files. -
ai-discovery-files/trunk/admin/class-admin.php
r3472044 r3472434 36 36 add_action( 'wp_ajax_aidf_validate_files', array( __CLASS__, 'ajax_validate_files' ) ); 37 37 add_action( 'wp_ajax_aidf_dismiss_welcome', array( __CLASS__, 'ajax_dismiss_welcome' ) ); 38 add_action( 'wp_ajax_aidf_save_verify_code', array( __CLASS__, 'ajax_save_verify_code' ) ); 38 39 add_action( 'admin_notices', array( __CLASS__, 'maybe_show_welcome_notice' ) ); 39 40 add_action( 'admin_notices', array( __CLASS__, 'maybe_show_conflict_notice' ) ); … … 114 115 'unknownError' => __( 'Unknown error', 'ai-discovery-files' ), 115 116 'crossFileConsistency' => __( 'Cross-File Consistency', 'ai-discovery-files' ), 117 'verifyFileActive' => __( 'Verification file is live at', 'ai-discovery-files' ), 118 'verifyFileInactive' => __( 'No verification code set. Enter your code above to activate.', 'ai-discovery-files' ), 116 119 ), 117 120 ) … … 226 229 227 230 wp_send_json_success( $results ); 231 } 232 233 /** 234 * AJAX handler: save domain verification code. 235 * 236 * @return void 237 */ 238 public static function ajax_save_verify_code() { 239 check_ajax_referer( 'aidf_admin_nonce', 'nonce' ); 240 241 if ( ! current_user_can( 'manage_options' ) ) { 242 wp_send_json_error( __( 'Permission denied.', 'ai-discovery-files' ) ); 243 } 244 245 $code = isset( $_POST['verify_code'] ) ? sanitize_text_field( wp_unslash( $_POST['verify_code'] ) ) : ''; 246 247 // Validate: must match "ai-visibility-verify=" followed by hex, or empty to clear. 248 if ( '' !== $code && ! preg_match( '/^ai-visibility-verify=[a-f0-9]+$/i', $code ) ) { 249 wp_send_json_error( __( 'Invalid verification code. The code should be in the format: ai-visibility-verify=abc123', 'ai-discovery-files' ) ); 250 } 251 252 $settings = get_option( 'aidf_settings', array() ); 253 $settings['verify_code'] = $code; 254 update_option( 'aidf_settings', $settings ); 255 256 // Flush rewrite rules to ensure the verify file route is active. 257 AIDF_Server::register_rewrite_rules(); 258 flush_rewrite_rules(); 259 260 $data = array( 261 'message' => empty( $code ) 262 ? __( 'Verification code removed.', 'ai-discovery-files' ) 263 : __( 'Verification code saved.', 'ai-discovery-files' ), 264 'active' => ! empty( $code ), 265 'url' => home_url( '/ai-visibility-verify.txt' ), 266 ); 267 268 wp_send_json_success( $data ); 228 269 } 229 270 -
ai-discovery-files/trunk/admin/class-settings.php
r3472044 r3472434 270 270 } 271 271 272 // Directory verification code — "ai-visibility-verify=" followed by hex. 273 if ( isset( $input['verify_code'] ) ) { 274 $code = sanitize_text_field( $input['verify_code'] ); 275 $clean['verify_code'] = ( '' === $code || preg_match( '/^ai-visibility-verify=[a-f0-9]+$/i', $code ) ) ? $code : $fallback['verify_code']; 276 } else { 277 $clean['verify_code'] = isset( $fallback['verify_code'] ) ? $fallback['verify_code'] : ''; 278 } 279 272 280 // Flush rewrite rules since active files may have changed. 273 281 AIDF_Server::register_rewrite_rules(); -
ai-discovery-files/trunk/admin/css/admin.css
r3472044 r3472434 1865 1865 } 1866 1866 1867 /* -------------------------------------------------------- 1868 23. Domain Verification Modal 1869 -------------------------------------------------------- */ 1870 1871 /* Backdrop */ 1872 .aidf-verify-modal { 1873 position: fixed; 1874 inset: 0; 1875 z-index: 100100; 1876 display: flex; 1877 align-items: center; 1878 justify-content: center; 1879 padding: var(--aidf-sp-5); 1880 animation: aidfModalFadeIn 0.2s ease-out; 1881 } 1882 1883 .aidf-verify-modal__backdrop { 1884 position: absolute; 1885 inset: 0; 1886 background: rgba(0, 0, 0, 0.6); 1887 backdrop-filter: blur(4px); 1888 -webkit-backdrop-filter: blur(4px); 1889 } 1890 1891 /* Card */ 1892 .aidf-verify-modal__card { 1893 position: relative; 1894 width: 100%; 1895 max-width: 580px; 1896 background: var(--aidf-white); 1897 border-radius: var(--aidf-radius-lg); 1898 box-shadow: 0 24px 80px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(0, 0, 0, 0.05); 1899 overflow: hidden; 1900 animation: aidfModalSlideUp 0.25s ease-out; 1901 } 1902 1903 /* Header */ 1904 .aidf-verify-modal__header { 1905 display: flex; 1906 align-items: center; 1907 justify-content: space-between; 1908 padding: var(--aidf-sp-5) var(--aidf-sp-6); 1909 background: linear-gradient(135deg, var(--aidf-dark) 0%, var(--aidf-dark-mid) 100%); 1910 color: var(--aidf-text-inverse); 1911 } 1912 1913 .aidf-verify-modal__header-content { 1914 display: flex; 1915 align-items: center; 1916 gap: var(--aidf-sp-3); 1917 } 1918 1919 .aidf-verify-modal__header-icon { 1920 display: flex; 1921 align-items: center; 1922 justify-content: center; 1923 width: 44px; 1924 height: 44px; 1925 background: linear-gradient(135deg, var(--aidf-orange) 0%, #ff9d42 100%); 1926 border-radius: 10px; 1927 flex-shrink: 0; 1928 } 1929 1930 .aidf-verify-modal__header-icon .dashicons { 1931 width: 22px; 1932 height: 22px; 1933 font-size: 22px; 1934 color: var(--aidf-dark); 1935 } 1936 1937 .aidf-verify-modal__title { 1938 font-size: 18px; 1939 font-weight: 700; 1940 color: var(--aidf-text-inverse); 1941 letter-spacing: -0.01em; 1942 line-height: 1.3; 1943 } 1944 1945 .aidf-verify-modal__subtitle { 1946 margin: 2px 0 0; 1947 font-size: 12px; 1948 color: rgba(255, 255, 255, 0.6); 1949 font-weight: 500; 1950 text-transform: uppercase; 1951 letter-spacing: 0.04em; 1952 } 1953 1954 .aidf-verify-modal__close { 1955 display: flex; 1956 align-items: center; 1957 justify-content: center; 1958 width: 32px; 1959 height: 32px; 1960 background: rgba(255, 255, 255, 0.1); 1961 border: none; 1962 border-radius: 6px; 1963 cursor: pointer; 1964 color: rgba(255, 255, 255, 0.7); 1965 transition: all 0.15s ease; 1966 } 1967 1968 .aidf-verify-modal__close:hover { 1969 background: rgba(255, 255, 255, 0.2); 1970 color: var(--aidf-text-inverse); 1971 } 1972 1973 .aidf-verify-modal__close .dashicons { 1974 width: 20px; 1975 height: 20px; 1976 font-size: 20px; 1977 } 1978 1979 /* Body */ 1980 .aidf-verify-modal__body { 1981 padding: var(--aidf-sp-6); 1982 } 1983 1984 .aidf-verify-modal__intro { 1985 margin-bottom: var(--aidf-sp-5); 1986 } 1987 1988 .aidf-verify-modal__intro p { 1989 margin: 0 0 var(--aidf-sp-2) 0; 1990 font-size: var(--aidf-text-sm); 1991 color: var(--aidf-text-secondary); 1992 line-height: 1.6; 1993 } 1994 1995 .aidf-verify-modal__intro p:last-child { 1996 margin-bottom: 0; 1997 } 1998 1999 /* Steps */ 2000 .aidf-verify-modal__steps { 2001 display: flex; 2002 flex-direction: column; 2003 gap: var(--aidf-sp-3); 2004 margin-bottom: var(--aidf-sp-5); 2005 padding: var(--aidf-sp-4); 2006 background: var(--aidf-bg); 2007 border-radius: var(--aidf-radius); 2008 border: 1px solid var(--aidf-border-light); 2009 } 2010 2011 .aidf-verify-modal__step { 2012 display: flex; 2013 align-items: center; 2014 gap: var(--aidf-sp-3); 2015 } 2016 2017 .aidf-verify-modal__step-number { 2018 display: flex; 2019 align-items: center; 2020 justify-content: center; 2021 width: 24px; 2022 height: 24px; 2023 background: var(--aidf-orange); 2024 color: var(--aidf-text-on-orange); 2025 border-radius: 50%; 2026 font-size: 12px; 2027 font-weight: 700; 2028 flex-shrink: 0; 2029 line-height: 1; 2030 } 2031 2032 .aidf-verify-modal__step-text { 2033 font-size: var(--aidf-text-sm); 2034 color: var(--aidf-text); 2035 line-height: 1.4; 2036 } 2037 2038 .aidf-verify-modal__step-text a { 2039 color: var(--aidf-orange); 2040 font-weight: 600; 2041 text-decoration: none; 2042 } 2043 2044 .aidf-verify-modal__step-text a:hover { 2045 color: var(--aidf-orange-hover); 2046 text-decoration: underline; 2047 } 2048 2049 /* Code input */ 2050 .aidf-verify-modal__field { 2051 margin-bottom: var(--aidf-sp-4); 2052 } 2053 2054 .aidf-verify-modal__label { 2055 display: block; 2056 margin-bottom: var(--aidf-sp-2); 2057 font-size: var(--aidf-text-sm); 2058 font-weight: 600; 2059 color: var(--aidf-text); 2060 } 2061 2062 .aidf-verify-modal__input { 2063 width: 100%; 2064 padding: 10px 14px; 2065 font-size: 14px; 2066 font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; 2067 letter-spacing: 0.02em; 2068 color: var(--aidf-text); 2069 background: var(--aidf-white); 2070 border: 1px solid var(--aidf-border); 2071 border-radius: var(--aidf-radius); 2072 outline: none; 2073 transition: border-color 0.15s ease, box-shadow 0.15s ease; 2074 box-sizing: border-box; 2075 } 2076 2077 .aidf-verify-modal__input:focus { 2078 border-color: var(--aidf-orange); 2079 box-shadow: 0 0 0 3px var(--aidf-orange-glow); 2080 } 2081 2082 .aidf-verify-modal__input::placeholder { 2083 color: var(--aidf-text-tertiary); 2084 font-family: var(--aidf-font); 2085 letter-spacing: normal; 2086 } 2087 2088 /* Status */ 2089 .aidf-verify-modal__status { 2090 display: flex; 2091 align-items: center; 2092 gap: var(--aidf-sp-2); 2093 padding: var(--aidf-sp-3) var(--aidf-sp-4); 2094 border-radius: var(--aidf-radius); 2095 font-size: var(--aidf-text-sm); 2096 color: var(--aidf-text-secondary); 2097 background: var(--aidf-bg); 2098 border: 1px solid var(--aidf-border-light); 2099 } 2100 2101 .aidf-verify-modal__status .dashicons { 2102 width: 18px; 2103 height: 18px; 2104 font-size: 18px; 2105 flex-shrink: 0; 2106 } 2107 2108 .aidf-verify-modal__status--active { 2109 background: var(--aidf-green-bg); 2110 border-color: var(--aidf-green-border); 2111 color: #15803d; 2112 } 2113 2114 .aidf-verify-modal__status--active .dashicons { 2115 color: var(--aidf-green); 2116 } 2117 2118 .aidf-verify-modal__status a { 2119 color: var(--aidf-orange); 2120 font-weight: 500; 2121 word-break: break-all; 2122 } 2123 2124 /* Footer */ 2125 .aidf-verify-modal__footer { 2126 display: flex; 2127 align-items: center; 2128 justify-content: space-between; 2129 padding: var(--aidf-sp-4) var(--aidf-sp-6); 2130 background: var(--aidf-bg); 2131 border-top: 1px solid var(--aidf-border-light); 2132 } 2133 2134 .aidf-verify-modal__footer-right { 2135 display: flex; 2136 gap: var(--aidf-sp-2); 2137 } 2138 2139 .aidf-verify-modal__dashboard-link { 2140 display: inline-flex; 2141 align-items: center; 2142 gap: 4px; 2143 font-size: var(--aidf-text-sm); 2144 color: var(--aidf-text-secondary); 2145 text-decoration: none; 2146 transition: color 0.15s ease; 2147 } 2148 2149 .aidf-verify-modal__dashboard-link:hover { 2150 color: var(--aidf-orange); 2151 } 2152 2153 .aidf-verify-modal__dashboard-link .dashicons { 2154 width: 14px; 2155 height: 14px; 2156 font-size: 14px; 2157 } 2158 2159 .aidf-verify-modal__footer .aidf-btn .dashicons { 2160 width: 16px; 2161 height: 16px; 2162 font-size: 16px; 2163 margin-right: 2px; 2164 } 2165 2166 /* Animations */ 2167 @keyframes aidfModalFadeIn { 2168 from { opacity: 0; } 2169 to { opacity: 1; } 2170 } 2171 2172 @keyframes aidfModalSlideUp { 2173 from { opacity: 0; transform: translateY(12px) scale(0.98); } 2174 to { opacity: 1; transform: translateY(0) scale(1); } 2175 } 2176 2177 /* -------------------------------------------------------- 2178 23b. CTA Verify Button Variant 2179 -------------------------------------------------------- */ 2180 .aidf-directory-cta__actions { 2181 display: flex; 2182 gap: var(--aidf-sp-2); 2183 flex-shrink: 0; 2184 } 2185 2186 .aidf-directory-cta__button--verify { 2187 background: transparent; 2188 border: 2px solid rgba(255, 255, 255, 0.5); 2189 color: var(--aidf-text-inverse); 2190 cursor: pointer; 2191 } 2192 2193 .aidf-directory-cta__button--verify:hover { 2194 background: rgba(255, 255, 255, 0.15); 2195 border-color: rgba(255, 255, 255, 0.8); 2196 color: var(--aidf-text-inverse) !important; 2197 transform: translateY(-1px); 2198 } 2199 2200 .aidf-directory-cta__button--verify .dashicons { 2201 width: 16px; 2202 height: 16px; 2203 font-size: 16px; 2204 } 2205 2206 /* -------------------------------------------------------- 2207 23c. Inline Verification Panel (Status Tab) 2208 -------------------------------------------------------- */ 2209 .aidf-verify-panel { 2210 margin-top: var(--aidf-sp-5); 2211 } 2212 2213 .aidf-verify-panel .aidf-panel-title .dashicons { 2214 margin-right: 6px; 2215 color: var(--aidf-orange); 2216 } 2217 2218 .aidf-verify-inline { 2219 display: flex; 2220 align-items: center; 2221 justify-content: space-between; 2222 gap: var(--aidf-sp-4); 2223 } 2224 2225 .aidf-verify-inline__status { 2226 display: flex; 2227 align-items: center; 2228 gap: var(--aidf-sp-2); 2229 font-size: var(--aidf-text-sm); 2230 } 2231 2232 .aidf-verify-inline__status--active { 2233 color: #15803d; 2234 } 2235 2236 .aidf-verify-inline__status--active .dashicons { 2237 color: var(--aidf-green); 2238 } 2239 2240 .aidf-verify-inline__status a { 2241 color: var(--aidf-orange); 2242 } 2243 2244 .aidf-verify-inline__description { 2245 margin: 0; 2246 font-size: var(--aidf-text-sm); 2247 color: var(--aidf-text-secondary); 2248 } 2249 2250 /* -------------------------------------------------------- 2251 24. Responsive 2252 -------------------------------------------------------- */ 2253 @media (max-width: 960px) { 2254 .aidf-header { 2255 padding: var(--aidf-sp-4) var(--aidf-sp-5); 2256 } 2257 2258 .aidf-tabs { 2259 padding: 0 var(--aidf-sp-4); 2260 overflow-x: auto; 2261 } 2262 2263 .aidf-content { 2264 padding: var(--aidf-sp-5); 2265 } 2266 2267 .aidf-file-grid { 2268 grid-template-columns: 1fr; 2269 } 2270 } 2271 1867 2272 @media (max-width: 782px) { 2273 .aidf-wrap { 2274 margin-left: -10px; 2275 } 2276 2277 .aidf-tabs { 2278 top: 46px; /* Mobile admin bar height */ 2279 } 2280 2281 .aidf-header-right { 2282 display: none; 2283 } 2284 2285 .aidf-header-version { 2286 display: none; 2287 } 2288 1868 2289 .aidf-directory-cta__content { 1869 2290 flex-direction: column; … … 1872 2293 } 1873 2294 2295 .aidf-directory-cta__actions { 2296 flex-direction: column; 2297 width: 100%; 2298 } 2299 1874 2300 .aidf-directory-cta__button { 1875 2301 width: 100%; 1876 2302 justify-content: center; 1877 2303 } 1878 } 1879 1880 /* -------------------------------------------------------- 1881 23. Responsive (formerly 22) 1882 -------------------------------------------------------- */ 1883 @media (max-width: 960px) { 1884 .aidf-header { 1885 padding: var(--aidf-sp-4) var(--aidf-sp-5); 2304 2305 .aidf-verify-modal__card { 2306 max-height: 90vh; 2307 overflow-y: auto; 1886 2308 } 1887 2309 1888 .aidf- tabs{1889 padding: 0 var(--aidf-sp-4);1890 overflow-x: auto;2310 .aidf-verify-modal__footer { 2311 flex-direction: column; 2312 gap: var(--aidf-sp-3); 1891 2313 } 1892 2314 1893 .aidf- content {1894 padding: var(--aidf-sp-5);2315 .aidf-verify-modal__footer-right { 2316 width: 100%; 1895 2317 } 1896 2318 1897 .aidf- file-grid{1898 grid-template-columns: 1fr;2319 .aidf-verify-modal__footer-right .aidf-btn { 2320 flex: 1; 1899 2321 } 1900 } 1901 1902 @media (max-width: 782px) { 1903 .aidf-wrap { 1904 margin-left: -10px; 2322 2323 .aidf-verify-inline { 2324 flex-direction: column; 2325 align-items: flex-start; 1905 2326 } 1906 1907 .aidf-tabs { 1908 top: 46px; /* Mobile admin bar height */ 1909 } 1910 1911 .aidf-header-right { 1912 display: none; 1913 } 1914 1915 .aidf-header-version { 1916 display: none; 1917 } 1918 } 1919 1920 /* -------------------------------------------------------- 1921 23. WordPress Admin Overrides 2327 } 2328 2329 /* -------------------------------------------------------- 2330 25. WordPress Admin Overrides 1922 2331 -------------------------------------------------------- */ 1923 2332 … … 1948 2357 1949 2358 /* -------------------------------------------------------- 1950 2 4. Welcome Notice (global WP admin)2359 26. Welcome Notice (global WP admin) 1951 2360 -------------------------------------------------------- */ 1952 2361 .aidf-welcome-notice { -
ai-discovery-files/trunk/admin/js/admin.js
r3472044 r3472434 461 461 }); 462 462 463 /* ------------------------------------------------------- 464 Domain Verification Modal 465 ------------------------------------------------------- */ 466 var verifyModal = $('#aidf-verify-modal'); 467 468 function openVerifyModal() { 469 verifyModal.show(); 470 $('body').css('overflow', 'hidden'); 471 verifyModal.find('#aidf-verify-code').focus(); 472 } 473 474 function closeVerifyModal() { 475 verifyModal.hide(); 476 $('body').css('overflow', ''); 477 } 478 479 // Open from CTA button or Status tab panel button. 480 $(document).on('click', '#aidf-open-verify-cta, #aidf-open-verify-panel', function (e) { 481 e.preventDefault(); 482 openVerifyModal(); 483 }); 484 485 // Close: X button, backdrop, Cancel button. 486 verifyModal.on('click', '[data-aidf-close-modal]', function () { 487 closeVerifyModal(); 488 }); 489 490 // Close: Escape key. 491 $(document).on('keydown', function (e) { 492 if (e.key === 'Escape' && verifyModal.is(':visible')) { 493 closeVerifyModal(); 494 } 495 }); 496 497 // Save verification code via AJAX. 498 $('#aidf-verify-save').on('click', function () { 499 var $btn = $(this); 500 var code = $('#aidf-verify-code').val().trim(); 501 var $status = $('#aidf-verify-status'); 502 503 $btn.prop('disabled', true).find('.dashicons').removeClass('dashicons-yes').addClass('dashicons-update'); 504 505 $.post(aidfAdmin.ajaxUrl, { 506 action: 'aidf_save_verify_code', 507 nonce: aidfAdmin.nonce, 508 verify_code: code 509 }, function (response) { 510 $btn.prop('disabled', false).find('.dashicons').removeClass('dashicons-update').addClass('dashicons-yes'); 511 512 if (!response.success) { 513 $status 514 .removeClass('aidf-verify-modal__status--active') 515 .html('<span class="dashicons dashicons-warning"></span> <span>' + escAttr(response.data) + '</span>'); 516 return; 517 } 518 519 var data = response.data; 520 521 if (data.active) { 522 $status 523 .addClass('aidf-verify-modal__status--active') 524 .html( 525 '<span class="dashicons dashicons-yes-alt"></span> ' + 526 '<span>' + escAttr(aidfAdmin.i18n.verifyFileActive) + ' ' + 527 '<a href="' + escAttr(data.url) + '" target="_blank" rel="noopener">' + escAttr(data.url) + '</a></span>' 528 ); 529 } else { 530 $status 531 .removeClass('aidf-verify-modal__status--active') 532 .html('<span class="dashicons dashicons-info-outline"></span> <span>' + escAttr(aidfAdmin.i18n.verifyFileInactive) + '</span>'); 533 } 534 535 // Flash the save button green briefly. 536 $btn.addClass('aidf-btn--success'); 537 setTimeout(function () { 538 $btn.removeClass('aidf-btn--success'); 539 }, 1500); 540 }).fail(function () { 541 $btn.prop('disabled', false).find('.dashicons').removeClass('dashicons-update').addClass('dashicons-yes'); 542 }); 543 }); 544 463 545 }); // end DOM ready 464 546 -
ai-discovery-files/trunk/admin/views/partials/directory-cta.php
r3472044 r3472434 46 46 </div> 47 47 48 <div class="aidf-directory-cta__action ">48 <div class="aidf-directory-cta__actions"> 49 49 <a href="https://www.ai-visibility.org.uk/submit/" 50 50 class="aidf-directory-cta__button" … … 54 54 <span class="dashicons dashicons-external"></span> 55 55 </a> 56 <button type="button" class="aidf-directory-cta__button aidf-directory-cta__button--verify" id="aidf-open-verify-cta"> 57 <span class="dashicons dashicons-shield-alt"></span> 58 <?php esc_html_e( 'Verify Domain', 'ai-discovery-files' ); ?> 59 </button> 56 60 </div> 57 61 </div> -
ai-discovery-files/trunk/admin/views/settings-page.php
r3472044 r3472434 95 95 ?> 96 96 <input type="hidden" name="aidf_settings[spec_attribution]" value="<?php echo esc_attr( $settings['spec_attribution'] ? '1' : '0' ); ?>" class="aidf-hidden-attribution"> 97 <input type="hidden" name="aidf_settings[verify_code]" value="<?php echo esc_attr( isset( $settings['verify_code'] ) ? $settings['verify_code'] : '' ); ?>"> 97 98 <?php endif; ?> 98 99 … … 114 115 <?php endif; ?> 115 116 </div> 117 118 <?php include AIDF_PLUGIN_DIR . 'admin/views/partials/verify-modal.php'; ?> 116 119 </div> -
ai-discovery-files/trunk/admin/views/tab-status.php
r3472044 r3472434 81 81 82 82 <input type="hidden" name="aidf_settings[spec_attribution]" value="<?php echo esc_attr( $settings['spec_attribution'] ? '1' : '0' ); ?>"> 83 <input type="hidden" name="aidf_settings[verify_code]" value="<?php echo esc_attr( isset( $settings['verify_code'] ) ? $settings['verify_code'] : '' ); ?>"> 83 84 84 85 <?php foreach ( $tiers as $tier_slug => $tier ) : ?> … … 175 176 </div> 176 177 </div> 178 179 <!-- Domain Verification --> 180 <?php 181 $verify_code = isset( $settings['verify_code'] ) ? $settings['verify_code'] : ''; 182 $verify_active = ! empty( $verify_code ); 183 ?> 184 <div class="aidf-panel aidf-verify-panel"> 185 <div class="aidf-panel-header"> 186 <div> 187 <h2 class="aidf-panel-title"> 188 <span class="dashicons dashicons-shield-alt"></span> 189 <?php esc_html_e( 'Directory Verification', 'ai-discovery-files' ); ?> 190 <?php if ( $verify_active ) : ?> 191 <span class="aidf-badge aidf-badge--essential"><?php esc_html_e( 'active', 'ai-discovery-files' ); ?></span> 192 <?php endif; ?> 193 </h2> 194 <p class="aidf-panel-subtitle"><?php esc_html_e( 'Prove domain ownership to manage your listing in the AI Visibility Directory.', 'ai-discovery-files' ); ?></p> 195 </div> 196 </div> 197 <div class="aidf-panel-body"> 198 <div class="aidf-verify-inline"> 199 <?php if ( $verify_active ) : ?> 200 <div class="aidf-verify-inline__status aidf-verify-inline__status--active"> 201 <span class="dashicons dashicons-yes-alt"></span> 202 <span> 203 <?php esc_html_e( 'Verification file is live at', 'ai-discovery-files' ); ?> 204 <a href="<?php echo esc_url( home_url( '/ai-visibility-verify.txt' ) ); ?>" target="_blank" rel="noopener"> 205 /ai-visibility-verify.txt ↗ 206 </a> 207 </span> 208 </div> 209 <?php else : ?> 210 <p class="aidf-verify-inline__description"> 211 <?php esc_html_e( 'After submitting your site to the directory, enter your verification code here so the plugin can serve the ownership file automatically.', 'ai-discovery-files' ); ?> 212 </p> 213 <?php endif; ?> 214 <button type="button" class="aidf-btn aidf-btn--secondary" id="aidf-open-verify-panel"> 215 <span class="dashicons dashicons-shield-alt"></span> 216 <?php 217 echo $verify_active 218 ? esc_html__( 'Update Verification Code', 'ai-discovery-files' ) 219 : esc_html__( 'Enter Verification Code', 'ai-discovery-files' ); 220 ?> 221 </button> 222 </div> 223 </div> 224 </div> -
ai-discovery-files/trunk/ai-discovery-files.php
r3472087 r3472434 4 4 * Plugin URI: https://www.ai-visibility.org.uk/wordpress-plugin/ai-discovery-files/ 5 5 * Description: Improve your AI Visibility by generating AI Discovery Files so AI systems like ChatGPT, Claude, and Gemini can correctly discover, interpret, and cite your website. 6 * Version: 1. 0.06 * Version: 1.1.0 7 7 * Requires at least: 6.2 8 8 * Requires PHP: 8.0 … … 24 24 * Plugin constants. 25 25 */ 26 define( 'AIDF_VERSION', '1. 0.0' );26 define( 'AIDF_VERSION', '1.1.0' ); 27 27 define( 'AIDF_PLUGIN_FILE', __FILE__ ); 28 28 define( 'AIDF_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); -
ai-discovery-files/trunk/includes/class-plugin.php
r3472044 r3472434 123 123 'active_files' => array( 'llms-txt', 'ai-txt' ), 124 124 'spec_attribution' => false, 125 126 // Directory verification. 127 'verify_code' => '', 125 128 ); 126 129 -
ai-discovery-files/trunk/includes/class-server.php
r3472044 r3472434 57 57 ); 58 58 } 59 60 // Domain verification file for AI Visibility Directory. 61 add_rewrite_rule( 62 '^ai-visibility-verify\.txt$', 63 'index.php?aidf_file=verify', 64 'top' 65 ); 59 66 } 60 67 … … 80 87 if ( empty( $file_slug ) ) { 81 88 return; 89 } 90 91 // Handle verification file separately (not an AI Discovery File). 92 if ( 'verify' === $file_slug ) { 93 $settings = AIDF_Plugin::get_settings(); 94 $verify_code = isset( $settings['verify_code'] ) ? $settings['verify_code'] : ''; 95 96 if ( empty( $verify_code ) ) { 97 status_header( 404 ); 98 nocache_headers(); 99 echo esc_html__( '404 — Verification file not configured.', 'ai-discovery-files' ); 100 exit; 101 } 102 103 status_header( 200 ); 104 header( 'Content-Type: text/plain; charset=utf-8' ); 105 header( 'Cache-Control: no-store' ); 106 header( 'X-Robots-Tag: noindex' ); 107 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Plain text output, validated on save. 108 echo $verify_code; 109 exit; 82 110 } 83 111 -
ai-discovery-files/trunk/readme.txt
r3472165 r3472434 3 3 Tags: ai, llms.txt, ai visibility, seo, chatgpt 4 4 Requires at least: 6.2 5 Tested up to: 6.9 .15 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 1. 0.07 Stable tag: 1.1.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 120 120 == Changelog == 121 121 122 = 1.1.0 = 123 * Add domain verification for the AI Visibility Directory 124 * New verification modal with step-by-step instructions 125 * Serve ai-visibility-verify.txt with user-supplied code 126 * Verify Domain button in directory CTA banner 127 * Verification panel on Status tab 128 * AJAX save for verification code (no page reload) 129 122 130 = 1.0.0 = 123 131 * Initial release … … 133 141 == Upgrade Notice == 134 142 143 = 1.1.0 = 144 New: Domain verification for the AI Visibility Directory. Serve your verification file directly from WordPress — no FTP needed. 145 135 146 = 1.0.0 = 136 147 Initial release. Install and configure your AI Discovery Files.
Note: See TracChangeset
for help on using the changeset viewer.