@Blog
過去の蓄積を見るために書く日記.

HTMLをMarkdownに変換する方法、PHP言語編
2025.09.07
おはようございます.HTMLをMarkdownに変換する方法、PHP言語編を書いています.これでワードプレスのLLMO対策しています.まず、自分はめんどくさがり屋なので、一からHTML(ハイパーテキストマークアップランゲージ)をマークダウン記法に変えるアルゴリズムを作るのは面倒なので今回は先人が作ったライブラリーを使用します.
composer require league/html-to-markdown
因みにこのライブラリーで変換出来ない、YOUTUBEの埋め込みなどは正規表現で置き換えています.
// カスタム:YouTube埋め込み対応
$content = preg_replace_callback(
'#<iframe[^>]+src="https?://www\.youtube\.com/embed/([^"?]+)[^"]*"[^>]*></iframe>#i',
function ($matches) {
$id = $matches[1];
return "\n[](https://www.youtube.com/watch?v={$id})\n";
},
$content
);
このライブラリーの使い方は、こちらのリードミーをご確認ください.人様のコードなのでいつサポートが切れるか分からないですが、当分の間は大丈夫そうな気がしています.もしサポートが非対応になったらフォークしてカスタマイズする方法も残されていますので、あまり気にしていませんが・・・.
一番怖いのはAPIの突然のサービス停止です、これが一番厄介だと思うのでこの頃はAPIサービスは極力使用しないように頑張っていますとは言ってもSNS系はAPIサービスに頼るしかないのが現状ですね.
明日へ続く
著者名
@taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
```, アルゴリズム, カスタマイズ, カスタム, コード, こちら, これ, サービス, サポート, そう, ダウン, ハイパーテキストマークアップランゲージ, フォーク, プレス, マーク, よう, ライブラリー, リードミー, ワード, 一番, 人様, 今回, 使い方, 使用, 停止, 先人, 厄介, 変換, 大丈夫, 対応, 対策, 当分, 方法, 明日, 正規, 現状, 確認, 自分, 表現, 言語, 記法, 面倒,

LLMO対策の前手順として、マークダウン記法を施しました.
2025.09.02
おはようございます.LLMO対策の前手順として、マークダウン記法を施しました.シングルページにマークダウン記法のリンクがそれぞれの記事にあると思います.
そのリンクをクリックするとマークダウン記法が表示されます.LLMO設置後、LLMs.txtを設置すれば良いらしいので、そちらも近日中に対応する予定です.尚、この記事がUPされている頃にはLLMs.txtの設置が終わっている気もします.
追伸:LLMs.txtの設置が終わりました、ルートに設置しています.LLMs.txtはマークダウン記法が記載されているURL(リンク)を一行ずつ表示するような形式で良いらしいです.
これをチャッピーさんにプラグインにして貰いましたのでお裾分けです.下記のプラグインを導入すると全記事URL(パラメーター(マークダウン記法と認識させる))が発行されます.
※マークダウン記法したページはご自身で作る必要があります.
<?php
/*
Plugin Name: LLMS URL Exporter (Fixed)
Description: 公開記事のURLをuploads/llms.txt に日付降順で出力します。管理画面のボタンで非同期(AJAX)実行。新規公開時は先頭に追記。
Version: 1.1
Author: taoka toshiaki
*/
if ( ! defined( 'ABSPATH' ) ) exit;
class LLMS_URL_Exporter {
private $file;
public function __construct() {
$this->file = $_SERVER['DOCUMENT_ROOT'] . '/llms.txt';
add_action( 'admin_menu', [ $this, 'add_admin_page' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_script' ] );
// AJAX (管理画面からの呼び出し = ログインユーザー用)
add_action( 'wp_ajax_llms_generate_urls', [ $this, 'generate_urls' ] );
// 投稿が公開になったとき(状態遷移を監視)
add_action( 'transition_post_status', [ $this, 'on_transition_post_status' ], 10, 3 );
register_activation_hook( __FILE__, [ $this, 'create_file_on_activate' ] );
}
public function create_file_on_activate() {
$dir = dirname( $this->file );
if ( ! is_dir( $dir ) ) {
wp_mkdir_p( $dir );
}
if ( ! file_exists( $this->file ) ) {
@file_put_contents( $this->file, "" );
}
}
public function add_admin_page() {
add_menu_page(
'LLMS URL Exporter',
'LLMS Export',
'manage_options',
'llms-url-exporter',
[ $this, 'admin_page_html' ]
);
}
public function enqueue_admin_script( $hook ) {
// 管理画面の当該ページだけに読み込む
if ( $hook !== 'toplevel_page_llms-url-exporter' ) return;
// jQuery は管理画面に既に存在
wp_enqueue_script( 'llms-admin', plugins_url( 'llms-admin.js', __FILE__ ), [ 'jquery' ], '1.0', true );
wp_localize_script( 'llms-admin', 'LLMS_Ajax', [
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'llms_generate_urls_nonce' ),
] );
// もし外部ファイルを用意しないなら、admin_page_html 内の inline script がフォールバックになります。
}
public function admin_page_html() {
?>
<div class="wrap">
<h1>LLMS URL Exporter</h1>
<p>公開中の全投稿URLを <code>/llms.txt</code> に日付降順で書き出します。</p>
<button id="llms-generate-btn" class="button button-primary">全記事URLを書き出す</button>
<div id="llms-result" style="margin-top:12px;"></div>
</div>
<?php
// フォールバック用のインラインスクリプト(もし外部 JS を作らない場合に有効)
$nonce = wp_create_nonce( 'llms_generate_urls_nonce' );
$ajax_url = admin_url( 'admin-ajax.php' );
?>
<script type="text/javascript">
jQuery(function($){
$('#llms-generate-btn').on('click', function(){
var $res = $('#llms-result');
$res.text('処理中...');
var data = {
action: 'llms_generate_urls',
_ajax_nonce: (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.nonce : '<?php echo esc_js( $nonce ); ?>')
};
var url = (typeof LLMS_Ajax !== 'undefined' ? LLMS_Ajax.ajax_url : '<?php echo esc_js( $ajax_url ); ?>');
$.post(url, data, function(response){
if ( response && response.success ) {
$res.html( response.data.message );
} else if ( response && response.data && response.data.message ) {
$res.html('エラー: ' + response.data.message);
} else {
$res.html('不明なレスポンス: ' + JSON.stringify(response));
}
}).fail(function(jqXHR, textStatus, errorThrown){
$res.html('AJAX エラー: ' + textStatus + ' ' + errorThrown + ' (status: ' + jqXHR.status + ')');
});
});
});
</script>
<?php
}
// AJAX ハンドラ
public function generate_urls() {
// nonce と権限チェック
check_ajax_referer( 'llms_generate_urls_nonce', '_ajax_nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => '権限がありません。' ], 403 );
}
$args = [
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'posts_per_page' => -1,
'no_found_rows' => true,
'fields' => 'ids',
];
$posts = get_posts( $args );
$urls = [];
foreach ( $posts as $pid ) {
$permalink = get_permalink( $pid );
if ( $permalink ) $urls[] = $permalink.'?md=1';
}
$content = implode("\n", $urls);
$written = @file_put_contents( $this->file, $content );
if ( $written === false ) {
$err = error_get_last();
$msg = isset( $err['message'] ) ? $err['message'] : '不明な書き込みエラー';
wp_send_json_error( [ 'message' => 'ファイル書き込みに失敗しました: ' . $msg ] );
}
wp_send_json_success( [ 'message' => 'llms.txt に ' . count( $urls ) . ' 件のURLを書き出しました。' ] );
}
// 公開判定:状態遷移で publish になったときに先頭へ追加
public function on_transition_post_status( $new_status, $old_status, $post ) {
if ( $post->post_type !== 'post' ) return;
if ( $new_status === 'publish' && $old_status !== 'publish' ) {
$url = get_permalink( $post->ID ).'?md=1';
$current = '';
if ( file_exists( $this->file ) ) {
$current = file_get_contents( $this->file );
}
// 既存の同一URLがあれば削除して先頭へ
$lines = array_filter( array_map( 'trim', explode("\n", $current ) ) );
$lines = array_values( array_diff( $lines, [ $url ] ) );
array_unshift( $lines, $url );
$new_content = implode("\n", $lines);
@file_put_contents( $this->file, $new_content );
}
}
}
new LLMS_URL_Exporter();
明日へ続く
著者名
@taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
```, いん, インライン, エラー, お裾分け, クリック, これ, サン, シングル, スクリプト, そちら, それぞれ, ダウン, チェック, チャッピー, とき, パラメーター, ハンドラ, ファイル, フォールバック, フラグ, ページ, ボタン, マーク, ユーザー, よう, リンク, ルート, レスポンス, ログイン, 一行, 下記, 不明, 予定, 先頭, 公開, 処理, 出力, 判定, 削除, 同一, 呼び出し, 場合, 外部, 失敗, 存在, 実行, 対応, 対策, 導入, 当該, 形式, 必要, 手順, 投稿, 新規, 既存, 日付, 明日, 書き込み, 有効, 権限, 状態, 用意, 画面, 発行, 監視, 管理, 自身, 表示, 記事, 記法, 記載, 設置, 認識, 近日, 追伸, 追加, 追記, 遷移, 降順, 非同期,

人工知能が読みやすいLLMO対策を近日中に対応.
2025.08.31
おはようございます.WordPressに人工知能が読みやすいLLMO対策を近日中に対応を施します.ただ、単にマークダウン記法で出力させるだけなんだけども、そんなに簡単でもないと思います.
簡単といえば簡単?知っているか知らないかで差が生まれるかも.
単なるコンテキストだけを抽出するならそんなに時間はかからないけど、記事の中にYOUTUBEやコードを埋め込んでいる場合はちょっと取り出し方に工夫がいるようになると思います.
取り出し方を知っているか知らないかで、差が発生すると思います.
因みにLLMO対策を何故するかは、これをしないと今後ページへ来てくれなくなる恐れがあるので速い内に対応しとこうと思ったわけです.
人工知能に記事を読んで貰いたいわけではないのだけど、AI(人工知能)モードが日本でも始まったらかなり打撃になることは確かなことだと思います.それぐらい脅威だと…
明日へ続く
著者名
@taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
コード, こと, これ, コンテキスト, それ, ダウン, ページ, マーク, モード, よう, わけ, 人工, 今後, 出力, 場合, 対応, 対策, 工夫, 恐れ, 打撃, 抽出, 日本, 明日, 時間, 発生, 知能, 確か, 簡単, 脅威, 記事, 記法, 近日,

Jsonの返却時に便利ですよを貼っときますねと雑煮.
2025.07.14
おはようございます.Jsonの返却時に便利ですよを貼っときますね、こう書くのがベストプラクティスなのか分かりませんが便利な時がありますので覚えておいて損はない書き方だと思います.
//Jsonの返却時に便利ですよ👍️
const obj = {
name: "Taoka",
age: 25,
country: "Japan"
};
Object.entries(obj).forEach(([key, value]) => {
console.log(key,value)
});
//console log ⬇️
//name Taro
//age 25
//country Japan
雑煮ではなくて雑談です、最近?のUPDATEでウィンドウズ11のメモ帳でもマークダウン記法が使えるようになったソウデス.ちょっと驚きました、なんかメモ帳ってウィルスに感染しないぐらい強固なアプリなイメージがあるので、いまのメモ帳は今まで無かったものを拡張していっている感じがしてちょっと心配なイメージが少しあります.
便利になることは良いことですが、拡張していくとバグや脆弱性が発生するので大丈夫かなって思います.マイクロソフト開発陣営は優秀な人だと思いますが、やっぱ心配.
全然関係ない話をもう一つウィンドウズをアップデートしていく内に何だか家のパソコンが熱暴走で…固まりだした.この原因を探ろうとログを見て解決したいと思っています.原因が分かったら記事にしようと思います.
明日へ続く
著者名
@taoka_toshiaki
※この記事は著者が40代前半に書いたものです.
Profile
高知県在住の@taoka_toshiakiです、記事を読んで頂きありがとうございます.
数十年前から息を吸うように日々記事を書いてます.たまに休んだりする日もありますがほぼ毎日投稿を心掛けています😅.
SNSも使っています、フォロー、いいね、シェア宜しくお願い致します🙇.
SNS::@taoka_toshiaki
タグ
```, アップデート, アプリ, いま, イメージ, ウィルス, ウィンドウズ, こと, そうです, ダウン, なん, バグ, パソコン, ベストプラクティス, マーク, マイクロソフト, メモ, もの, よう, ログ, 一つ, 便利, 優秀, 原因, 大丈夫, 強固, 心配, 感じ, 感染, 拡張, 明日, 暴走, 書き方, 最近, 発生, 脆弱, 解決, 記事, 記法, 返却, 開発, 関係, 陣営, 雑煮, 雑談,