晴歩雨描

晴れた日は外に出て歩き、雨の日は部屋で絵を描く

WordPress)はてなブログから移行した画像をポップアップ表示するようにした。

はてなブログからWordPressへの移行を検証している。

はてなブログからWordPressへ画像を移行して記事内で画像が表示されるようになったが、この画像をクリックしてポップアップ画像を表示するようにした。

<a>タグ、<div>タグを使わずに、<img>タグだけで画像を、ポップアップする方法を利用した。

テーマフォルダ「\wp-content\themes\iconic-one\」の以下のファイルにそれぞれ追記。

ポップアップする対象の画像は、class名が「hatena-fotolife」のものだけ。

<p><img class="hatena-fotolife" ....></p>
custom.css

※ ポップアップ画像がWordPressのヘッダーに隠れないように調整。

※ ポップアップ画像には白枠と角丸も付けている。

#modal-container {
	display: none;
	position: fixed;
	background: rgba(0, 0, 0, 0.6);
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 99;
}
#modal-container > div {
	display: flex;
	height: 100vh;
	justify-content: center;
	align-items: center;
}
#modal-container > div > img {
	max-width: calc(100vw - 50px);
	max-height: calc(100vh - 100px);
	margin-top: 30px;
	padding: 12px;
	background-color: #fff;
	box-shadow: 0 3px 18px -4px rgba(0, 0, 0, 0.8);
	border-radius: 10px;
}
p > img.hatena-fotolife {
	cursor: pointer;
}
figure > img.hatena-fotolife {
	cursor: pointer;
}
header.php

jQueryを使う。

<script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script>
footer.php

※ 既に<a>タグで囲われている<img>タグは除くため、<p>タグと<figure>タグ直下だけを対象にしている。

<div id="modal-container"><div><img src=""></div></div>
<script>
const modal = $('#modal-container');
const img = modal.find('img');
$('p > img.hatena-fotolife').each(function(index) {	// <p>直下の<img>だけ対象
	$(this).click(function() {
		img.attr('src', $(this).attr('src'));
		modal.show();
	})
});
$('figure > img.hatena-fotolife').each(function(index) {	// <figure>直下の<img>だけ対象
	$(this).click(function() {
		img.attr('src', $(this).attr('src'));
		modal.show();
	})
});
modal.click(function() {
	$(this).hide();
});
</script>

JavaScript、CSS)aタグ、divタグを使わずに、imgタグだけで画像をポップアップする。

HTMLで画像をポップアップする場合、<a>タグや<div>タグで<img>タグを囲んで行うのが一般的。

<a>タグ、<div>タグを使わずに、<img>タグだけで画像をポップアップする方法を探した。以下に目的のものがあった。

CSS
<style>
#modal-container {
	display: none;
	position: fixed;
	background: rgba(0, 0, 0, 0.6);
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 99;
}
#modal-container > div {
	display: flex;
	height: 100vh;
	justify-content: center;
	align-items: center;
}
#modal-container > div > img {
	max-width: calc(100vw - 30px);
	max-height: calc(100vh - 30px);
}
img.popup {
	cursor: pointer;
	width: 300px;
}
</style>
≪HTMLサンプル≫
<img class="popup" src="img/photo1.jpg">
<img class="popup" src="img/photo2.jpg">
<div id="modal-container">
	<div><img src=""></div>
</div>
JavaScript

jQueryを使っている。

<script>
const modal = $('#modal-container');
const img = modal.find('img');
$('img.popup').each(function(index) {
	$(this).click(function() {
		img.attr('src', $(this).attr('src'));
		modal.show();
	})
});
modal.click(function() {
	$(this).hide();
});
</script>
≪テスト用ページ≫

ポップアップした画像。

更に、ポップアップ画像に白枠と角丸を付けた。

CSS 追加≫
#modal-container > div > img {
	max-width: calc(100vw - 30px);
	max-height: calc(100vh - 30px);
	padding: 12px;
	background-color: #fff;
	box-shadow: 0 3px 18px -4px rgba(0, 0, 0, 0.8);
	border-radius: 10px;
}

↓↓↓ この方法を、WordPressで使ってみた。

↓↓↓ この方法を、「My 野鳥図鑑」でも使ってみた。

はてなブログエクスポートファイルからキーワードリンク<a>タグを除去するJScript。WordPressインポート用。

はてなブログでは、文章中の特定のキーワードに勝手にアンダーラインが引かれリンクになる。

無料版では標準的にはこれを消せない。

はてなブログからエクスポートするファイルにも、そのキーワードリンクはそのまま残っている。

≪サンプル≫

<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%FE%C5%D4%C9%DC%CE%A9%BF%A2%CA%AA%B1%E0">京都府立植物園</a>

はてなブログエクスポートファイルから、このキーワードリンク<a>タグを除去するJScriptスクリプト

//	ドラッグ&ドロップしたパス情報を取得
var args = WScript.Arguments;
var inputFile = args(0);

var sr = new ActiveXObject("ADODB.Stream");
sr.Type = 2;					// adTypeText
sr.charset = "utf-8";
sr.Open();
sr.LoadFromFile(inputFile);
var str = sr.ReadText(-1);			// adReadAll
sr.Close();

var out = str.replace(new RegExp('<a[^>]+href=\"https?://d\.hatena\.ne\.jp/keyword.*?>(.*?)</a>', 'g'), '$1')

var sw = new ActiveXObject("ADODB.Stream");
sw.Type = 2;					// adTypeText
sw.charset = "utf-8";
sw.Open();
sw.WriteText(out, 1);				// adWriteLine
sw.SaveToFile(inputFile.slice(0,-4) + "-remove.txt", 2);	// adSaveCreateOverWrite
sw.Close();

<a>タグを除去する正規表現については、「teratail」で教えてもらった。


JavaScript)EUC-JPエンコード→UTF-8エンコード変換。

はてなブログでは、文章中の特定のキーワードに勝手にアンダーラインが引かれリンクになる。

無料版では標準的にはこれを消せない。

はてなブログからエクスポートするファイルにも、そのキーワードリンクはそのまま残っている。

≪サンプル「京都府立植物園」≫

<a class="keyword" href="http://d.hatena.ne.jp/keyword/%B5%FE%C5%D4%C9%DC%CE%A9%BF%A2%CA%AA%B1%E0">京都府立植物園</a>

キーワードがURIエンコードされているのだが、これが「EUC-JP」ベース。

このエンコード文字列をそのままWikipediaに渡すとエラーになる。Wikipediaエンコードは「UTF-8」ベースのため。

≪サンプル「京都府立植物園」≫

https://ja.wikipedia.org/wiki/%E4%BA%AC%E9%83%BD%E5%BA%9C%E7%AB%8B%E6%A4%8D%E7%89%A9%E5%9C%92

JavaScriptには「UTF-8」のURIエンコード/デコードをする関数は標準にある。

  • encodeURI()
  • decodeURI()

EUC-JP」のURIエンコード/デコードはない。

探してみると、「Escape Codec Library: ecl.js」というのが見つかった。

これを使えば、EUC-JPエンコード文字列をUTF-8エンコードに変換できる。

UnescapeEUCJP()」で、EUC-JPエンコードをデコードして、encodeURI()でUTF-8エンコードする。

<script>
var eucEnc = "%B5%FE%C5%D4%C9%DC%CE%A9%BF%A2%CA%AA%B1%E0";
var utf8 = UnescapeEUCJP(eucEnc);
var utf8Enc = encodeURI(utf8);
</script>

WordPress)はてなブログから移行(インポート)する手順まとめ。メディアライブラリを使わないバージョン。

自宅WindowsPCローカルにWordPressをインストールしている。

はてなブログ」からエクスポートしてWordPressにインポートしてみた。

以前、移行(インポート)する手順まとめを書いた。この時はメディアライブラリを使う前提だった。

メディアライブラリを使わないで、アイキャッチ画像表示する方法が分かったので、

今回は、メディアライブラリを使わない前提の移行(インポート)手順まとめ。

1.はてなブログエクスポートファイル加工。

はてなブログエクスポートファイルを以下の手順で加工する。

(例)はてなブログエクスポートファイル「2ndart.hatenablog.com.export.txt」

1.1 アイキャッチ画像CSV生成 ≪eyecatch-csv.jse
  • 入力:2ndart.hatenablog.com.export.txt(ファイル名固定)
  • 出力:hatena.eyecatch.csv
1.2 画像URLをローカルパスURLに変更 ≪hatena-img-chg.jse
1.3 はてなブログカード→Wordpressショートコード変換 ≪blogcard-chg.jse
  • 入力:「1.2」の出力ファイル(ドラッグ&ドロップ
  • 出力:2ndart.hatenablog.com.export-imgchg-blogcard.txt
1.4 (任意) キーワードリンク<a>タグを除去する ≪keyword-remove.jse≫
  • 入力:「1.3」の出力ファイル(ドラッグ&ドロップ
  • 出力:2ndart.hatenablog.com.export-imgchg-blogcard-remove.txt
1.5 アイキャッチ用画像挿入 ≪eyecatch-insert.jse
  • 入力:「1.3」または「1.4」の出力ファイル(ドラッグ&ドロップ
  • 出力:2ndart.hatenablog.com.export-imgchg-blogcard-remove-eyecatchtxt

上記それぞれのスクリプトの詳細は以下。

2.エクスポートファイル ⇒ インポート。

上記手順1で加工したはてなブログ「エクスポートファイル」をダッシュボードでインポートする。

※ インポートは「エクスポートファイル」2MB単位でしかできないので、分割して行う。

「ツール」の「Movable TypeTypePad」の「今すぐインストール 」を実行。

「インポーターの実行」が表示されるので実行。

Movable Type もしくは Typepad のインポート」画面が出る。

はてなブログでエクスポートしたMT(MovableType)形式のテキストファイルを選択して「ファイルをアップロードしてインポート」を実行。

※ インポートファイルは最大サイズ2MBと出るが、追加で複数ファイルをインポートできる。ちゃんと日付順に表示される。

3.画像ファイル:格納。

はてなブログの画像ファイルは、以下のツールでダウンロードする。

ダウンロードした画像ファイルを「\wp-content\uploads\hatena」に入れる。

※ 今回の方法では、メディアライブラリやWordPressアイキャッチ画像は使わないので、メディアライブラリへの登録やアイキャッチ画像の登録といった作業は不要。


以下、画像格納フォルダを年別の階層構造にした場合のJScript改訂版のソースリスト。

  • \wp-content\uploads\hatena\2019
  • \wp-content\uploads\hatena\2020
  • \wp-content\uploads\hatena\2021
  • \wp-content\uploads\hatena\2022
1.1 アイキャッチ画像CSV生成 ≪eyecatch-csv.jse≫
var adTypeText = 2;
var adSaveCreateOverWrite = 2;	// 上書き
var adReadAll = -1;		// 全行

var sr = new ActiveXObject("ADODB.Stream");
sr.Type = adTypeText;
sr.charset = "utf-8";
sr.Open();
sr.LoadFromFile("2ndart.hatenablog.com.export.txt");	// ファイル名固定
var str = sr.ReadText(adReadAll);
sr.Close();

var sw = new ActiveXObject("ADODB.Stream");
sw.type = adTypeText;
sw.charset = "utf-8";
sw.Open();

var body = false;	// BODY:
var bodyend = true;	// --------
var out = "";
var line_ary = str.split(/\n/);
for (var i=0; i<line_ary.length; i++) {
	if (!body) {
		if (line_ary[i].substring(0,10) == 'BASENAME: ') {
			var base = line_ary[i].slice(10);
			var spt = base .split('/');
			var str = spt[0] + '/' + spt[1] + '/' + spt[2] + '/' + spt[0] + '-' + spt[1] + '-' + spt[2] + '-' + spt[3];
			out = out + 'wordpress/' + str + ",";
		}
		if (line_ary[i].substring(0,7) == 'IMAGE: ') {
			var image = line_ary[i].slice(7);
			var spt = image.split('/');
			out = out + spt[7].substring(0,4) + '/' + spt[7] + '_' + spt[8] + "\n";
		}
	}
	if (line_ary[i].substring(0,5) == 'BODY:') {
		body = true;
		bodyend = false;
	}
	if (line_ary[i] == '-----') {
		bodyend = true;
		body = false;
	}
}
sw.WriteText(out);
sw.SaveToFile("hatena.eyecatch.csv",adSaveCreateOverWrite);
sw.Close();
1.2 画像URLをローカルパスURLに変更 ≪hatena-img-chg.jse≫
//	ドラッグ&ドロップしたパス情報を取得
var args = WScript.Arguments;
var inputFile = args(0);

var sr = new ActiveXObject("ADODB.Stream");
sr.Type = 2;					// adTypeText
sr.charset = "utf-8";
sr.Open();
sr.LoadFromFile(inputFile);
var str = sr.ReadText(-1);			// adReadAll
sr.Close();

var tmp = str.replace(/https:\/\/cdn-ak\.f\.st-hatena.com\/images\/fotolife\/a\/art2nd\//g,'/wordpress/wp-content/uploads/hatena/ZXZXZX');

var tmp2 = "";
var out = tmp.replace(/ZXZXZX(\d{8})\/(\d{14}\.(jpg|png|gif))/g,function() {
	tmp2 = arguments[0].replace('\/', '_').replace('ZXZXZX', '');
	return tmp2.substring(0,4) + '/' + tmp2;
});

var sw = new ActiveXObject("ADODB.Stream");
sw.Type = 2;					// adTypeText
sw.charset = "utf-8";
sw.Open();
sw.WriteText(out, 1);				// adWriteLine
sw.SaveToFile(inputFile.slice(0,-4) + "-imgchg.txt", 2);	// adSaveCreateOverWrite
sw.Close();
1.3 はてなブログカード→Wordpressショートコード変換 ≪blogcard-chg.jse≫
//	***	ドラッグ&ドロップしたパス情報を取得
var args = WScript.Arguments;
var inputFile = args(0);

var adTypeText = 2;
var adSaveCreateOverWrite = 2;	// 上書き
var adReadAll = -1;		// 全行

var sr1 = new ActiveXObject("ADODB.Stream");
sr1.Type = adTypeText;
sr1.charset = "utf-8";
sr1.Open();
sr1.LoadFromFile(inputFile);	//  はてなブログ エクスポート・ファイル

var str = sr1.ReadText( adReadAll );
sr1.Close();

var stw = new ActiveXObject("ADODB.Stream");
stw.type = adTypeText;
stw.charset = "utf-8";
stw.Open();

var out = "";
var lines = str.split(/\r?\n/);
var card = false;
for (var i=0, z=lines.length; i<z; i++) {
	card = false;
	var iframe = lines[i].match(/<iframe(.*)<\/iframe>/);
	if (iframe) {
		var src = iframe[1].match(/src="https?:\/\/hatenablog-parts.com\/embed\?url\=https?%3A%2F%2F2ndart\.hatenablog.com%2Fentry%2F(.*)" /);		// 何故か "以降も入ってくる。
		if (src) {
			var urlymd = src[1].split('"');
			if (urlymd) {
				var spt = urlymd[0] .split('%2F');
				var ymd = spt[0] + '/' + spt[1] + '/' + spt[2] + '/' + spt[0] + '-' + spt[1] + '-' + spt[2] + '-' + spt[3];
				out = out + '<p>[nmblogcard url="/wordpress/' + ymd + '/"]</p>\n';
				card = true;
			}
		}
	}
	if (!card) {
		out = out + lines[i] + "\n";
	}
}
stw.WriteText(out);
stw.SaveToFile(inputFile.slice(0,-4) + "-blogcard.txt", adSaveCreateOverWrite);
stw.Close();
1.4 キーワードリンク<a>タグを除去する ≪keyword-remove.jse≫
//	ドラッグ&ドロップしたパス情報を取得
var args = WScript.Arguments;
var inputFile = args(0);

var sr = new ActiveXObject("ADODB.Stream");
sr.Type = 2;					// adTypeText
sr.charset = "utf-8";
sr.Open();
sr.LoadFromFile(inputFile);
var str = sr.ReadText(-1);			// adReadAll
sr.Close();

var out = str.replace(new RegExp('<a[^>]+href=\"https?://d\.hatena\.ne\.jp/keyword.*?>(.*?)</a>', 'g'), '$1')

var sw = new ActiveXObject("ADODB.Stream");
sw.Type = 2;					// adTypeText
sw.charset = "utf-8";
sw.Open();
sw.WriteText(out, 1);				// adWriteLine
sw.SaveToFile(inputFile.slice(0,-4) + "-remove.txt", 2);	// adSaveCreateOverWrite
sw.Close();
1.5 アイキャッチ用画像挿入 ≪eyecatch-insert.jse≫

※ エクスポートファイルをドラッグ&ドロップで読み込む場合、他のインプットファイル(CSVファイル:hatena.eyecatch.csv)も絶対パスにしないとエラーになる。

var args = WScript.Arguments;		// ドラッグ&ドロップしたパス情報を取得
var inputFile = args(0);		// はてなブログ エクスポート・ファイル(2,3処理済み)(絶対パス)

var csvFile = "hatena.eyecatch.csv";
var fso = new ActiveXObject("Scripting.FileSystemObject");
var path = fso.getParentFolderName(WScript.ScriptFullName);	// カレントディレクトリ(絶対パス)
var csvFile = path + "\\" + csvFile;	// csvFile:絶対パスに変換
var adTypeText = 2;
var adSaveCreateOverWrite = 2;		// 上書き
var adReadAll = -1;			// 全行
// ---------------------------------
var sr1 = new ActiveXObject("ADODB.Stream");
sr1.Type = adTypeText;
sr1.charset = "utf-8";
sr1.Open();
sr1.LoadFromFile(csvFile);
var csvstr = sr1.ReadText(adReadAll);
sr1.Close();

var csvlines = csvstr.split(/\r?\n/);
var eyecatch = [];
for (var i=0; i<csvlines.length; i++) {
	eyecatch[i] = csvlines[i].split(",");
}
// ---------------------------------
var sr2 = new ActiveXObject("ADODB.Stream");
sr2.Type = adTypeText;
sr2.charset = "utf-8";
sr2.Open();
sr2.LoadFromFile(inputFile);
var str = sr2.ReadText(adReadAll);
sr2.Close();

var stw = new ActiveXObject("ADODB.Stream");
stw.type = adTypeText;
stw.charset = "utf-8";
stw.Open();

var out = "";
var lines = str.split(/\r?\n/);
var outsw = false;
var image = "";
for (var i=0; i<lines.length; i++) {
	outsw = false;
	if (lines[i].substring(0,7) == 'IMAGE: ') {
		image = lines[i].slice(7);
	}
	if (lines[i].substring(0,5) == 'BODY:') {
		if (image != "") {
			out = out + 'BODY:' + "\n" + '<img src="' + image + '" style="display:none;">' + "\n";
			outsw = true;
			image = "";
		}
	}
	if (lines[i].indexOf('<p>[nmblogcard url="/wordpress/') == 0) {
		url = lines[i].substr(21).slice(0,-7);
		if (imgfile = array2find(url, eyecatch)) {
			out = out + lines[i].slice(0,-5) + ' image_url="/wordpress/wp-content/uploads/hatena/' + imgfile + '"]</p>' + "\n";
			outsw = true;
		}
	}
	if (!outsw) {
		out = out + lines[i] + "\n";
	}
}
stw.WriteText(out);
stw.SaveToFile(inputFile.slice(0,-4) + "-eyecatch.txt", adSaveCreateOverWrite);
stw.Close();
function array2find(str, ary) {
	for (var i=0; i<ary.length; i++) {
		if (str == ary[i][0]) {
			return ary[i][1];
		}
	}
	return false;
}

※ メディアライブラリを使わない設定まとめは、以下。