is_enabled() ) { status_header( 404 ); exit; } header( 'Content-Type: text/plain; charset=utf-8' ); header( 'X-Robots-Tag: noindex' ); echo $this->generate(); // phpcs:ignore WordPress.Security.EscapeOutput -- プレーンテキスト出力。 exit; } public function is_enabled() { $options = get_option( 'acsaiv_options', array() ); return ! empty( $options['llms_txt_enabled'] ); } /** * llmstxt.org 仕様に沿ったMarkdownを生成する。 */ public function generate() { $options = get_option( 'acsaiv_options', array() ); $description = ! empty( $options['site_description'] ) ? $options['site_description'] : get_bloginfo( 'description' ); $post_count = isset( $options['llms_post_count'] ) ? max( 1, min( 50, (int) $options['llms_post_count'] ) ) : 10; $lines = array(); $lines[] = '# ' . get_bloginfo( 'name' ); $lines[] = ''; if ( $description ) { $lines[] = '> ' . $this->flatten( $description ); $lines[] = ''; } // 固定ページ。 $pages = get_pages( array( 'sort_column' => 'menu_order', 'number' => 30 ) ); if ( $pages ) { $lines[] = '## ' . __( 'Main Pages', 'acs-ai-citation-readiness' ); $lines[] = ''; foreach ( $pages as $page ) { $lines[] = $this->link_line( $page ); } $lines[] = ''; } // 最新記事。 $posts = get_posts( array( 'numberposts' => $post_count, 'post_status' => 'publish' ) ); if ( $posts ) { $lines[] = '## ' . __( 'Recent Posts', 'acs-ai-citation-readiness' ); $lines[] = ''; foreach ( $posts as $post ) { $lines[] = $this->link_line( $post ); } $lines[] = ''; } return implode( "\n", $lines ); } private function link_line( $post ) { $title = $this->flatten( get_the_title( $post ) ); $url = get_permalink( $post ); $excerpt = $this->flatten( get_the_excerpt( $post ) ); $line = sprintf( '- [%s](%s)', $title, $url ); if ( $excerpt ) { $line .= ': ' . mb_substr( $excerpt, 0, 80 ); } return $line; } private function flatten( $text ) { return trim( preg_replace( '/\s+/u', ' ', wp_strip_all_tags( (string) $text ) ) ); } }