印刷向けの CSS 機能がブラウザより整っていたりして良いツールなのですが 日本語で使おうとすると問題点があり 将来性の期待はあるものの実用はしてない状況でした
久々に使って 色々更新されてるし問題点も対応されてるかなと思ったのですが まだ対応されてませんでした
フォント関係なので CJK のフォントを使わないならほとんど関係なさそうですし 優先度は低そうです
内容的に将来的にも対応されるかもわからないです
問題のひとつは CID キー付きフォントに対応してないことです
https://github.com/Kozea/WeasyPrint/issues/1593
日本語のフォントで有名な
源ノ角ゴシック (Source han sans)
源ノ明朝 (Source han serif)
など のフォントは CID キー付きフォントになってるようです
効率的に保存できるらしいので 多くの文字を保持しているフォントはたぶんほとんどこれなのでしょう
これらのフォントを WeasyPrint で使うと問題なく PDF は出力できるのですが 一部の環境では CJK の文字が表示されません
Edge などブラウザでは問題ないようなのですが PDF である以上 一般的なビューワー全てで見れないというのは使えない場合があります
ところで 源ノ明朝って 「げんのみんちょう」 って読むらしいです
「みなもと」 だと思ってたのに
(みなもとのよりともって呼んでる人多いよね?)
そういう問題があるので別のフォントを探して見つかったのが IPA フォント
これは CID キー付きフォントではないようです
しかしこれは別の問題がありました
太字・斜体にできません
最近の可変フォントを除けば 太字や斜体って別にフォントが用意されているものです
regular とか medium など太さがフォントの名前についてたりします
そうでないフォントは フォントとして太字のデータはないので 表示する側で擬似的に太字にしています
自動でやる分 ちゃんとフォントが別にあるものより汚いみたいです
WeasyPrint はこの疑似的に太字にしたり斜体にしたりする機能をサポートしていません
太字や斜体にしたいなら それに対応したフォントを使うか b や strong タグのスタイルに別の太字・斜体フォントを指定してという方針みたいです
しかし IPA フォントを始め多くのフォントって太さの違いを別フォントにしてないです
これのせいで太字が使えません
Windows にインストールされている標準のフォントを見ると MS ゴシックや MS 明朝はフォントが太さのフォントは用意されていないようです
メイリオや游ゴシックはフォントが用意されていました
しかし WeasyPrint を実行するのは Linux 環境です
個人で使う程度なら気にしなくてもいいのかもですが ライセンス的にはアウトだと思います
それにこれらのフォントが CID キー付きフォントでないかは未確認です
そんなわけで WeasyPrint で使える良い日本語フォントがなくて使えない状況です
マイナーフォントを探せば CID キー付きではなく太さごとにフォントファイルが用意されたフォントもあるかもしれないですが あまり変わった書体ではなく よくある一般的なものにしたいのですよね
将来的に WeasyPrint がこれらをサポートしてくれるといいのですが あまり期待もできません
太さの問題は過去バージョンは対応していたのに 内部的に PDF 生成やフォントを扱うツールを変えてから対応しなくなったようです
しばらく修正されないままですし 使うツールの都合上対応が難しそうなことも書かれています
https://github.com/Kozea/WeasyPrint/issues/1470
太さが違うフォントを指定すればいいという回避策もある以上期待できないです
CID キー付きフォントの方は調べてもいまいちよくわからないものです
レガシーという記述があったりなかったり
CID フォントと言っても種類があるようで sfnt wrapped という形式の CID フォントがレガシーらしいです
OpenType のものはそれとは違って問題ないように書いてるページもありました
https://ccjktype.fonts.adobe.com/wp-content/uploads/2018/12/cjkv2e-pp387-393.pdf
逆に CID キー付きフォントは この sfnt wrapped の CID を含むレガシーフォーマットと言う記載もあります
https://github.com/fontforge/fontforge/wiki/Community-guidelines#d6-cid-keyed-fonts
よくわからないですが フォント系を扱う有名なツールの fontforge がレガシーだから積極的にサポートしないといってるくらいです
WeasyPrint が対応する期待はできません
ブラウザ自体がもっと印刷や PDF 対応を頑張ってくれるといいのですが 印刷需要が少ないのであまり期待はできないですね
普通に @font-face で url に相対パスを指定すれば動く
扱い的に local ぽいけど local はインストール済みフォントをパスではなく名前指定で探すもの
(例)
フォントは 「M PLUS 1 Code」 を使用
Google Fonts でダウンロード
https://fonts.google.com/specimen/M+PLUS+1+Code?query=Coji+Morishita&vfonly=true
index.html と index.css と MPLUS1Code-Regular.ttf を同じフォルダに配置
[index.html]
[index.css]
コマンド
結果

扱い的に local ぽいけど local はインストール済みフォントをパスではなく名前指定で探すもの
(例)
フォントは 「M PLUS 1 Code」 を使用
Google Fonts でダウンロード
https://fonts.google.com/specimen/M+PLUS+1+Code?query=Coji+Morishita&vfonly=true
index.html と index.css と MPLUS1Code-Regular.ttf を同じフォルダに配置
[index.html]
<!doctype html>
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="./index.css"/>
</head>
<body>
<h1>H1</h1>
<pre><code class="">function a() {<br/> console.log("!#$%&{}+*@|?")<br/> return 1<br/>}</code></pre>
<pre><code class="font1">function a() {<br/> console.log("!#$%&{}+*@|?")<br/> return 1<br/>}</code></pre>
<pre><code class="font2">function a() {<br/> console.log("!#$%&{}+*@|?")<br/> return 1<br/>}</code></pre>
</body>
[index.css]
@font-face {
font-family: "mp1c";
src: url("MPLUS1Code-Regular.ttf");
}
pre code {
display: block;
border: 1px solid #000;
padding: 5px;
}
.font1 {
font-family: monospace;
}
.font2 {
font-family: mp1c;
}
コマンド
weasyprint index.html out.pdf
結果

WeasyPrint は PDF 作成に特化してるのでブラウザでは使えない CSS も使える
結構古い Working Draft だけどこの辺
https://www.w3.org/TR/2014/WD-css-gcpm-3-20140513/
string-set プロパティと string 関数が使えるので セクションタイトルをページの右上に常に表示したいなら
という感じで h1 のスタイルで string-set を指定して heading に h1 タグ内の content を設定
右上のヘッダ部分の content で heading を参照
これでヘッダにセクションタイトルを設定できる
それならドキュメントタイトルを左上に表示にしたければ title タグに同じようなことをすればできるはず
これで表示されるかと思ったけど表示されない
title タグは head タグの中だからスタイルの対象外?
調べると head タグの中ではなく display: none の要素は対象外らしい
https://github.com/Kozea/WeasyPrint/issues/473
回避策は head と title タグを display: none じゃなくすることらしい
だけど head タグを block にすると表示対象になるのでその中も表示される
head タグ内の他のタグ(style タグなど)は display: none だから 問題は title タグ自身も表示されること
これを避けるために visibility を hidden にする
それだけだと見えないだけでレイアウトに影響するのでサイズを 0 にする
これで左上にドキュメントタイトルが表示できるようになった
結構前からある問題みたいだし そろそろ修正されて欲しいけど
結構古い Working Draft だけどこの辺
https://www.w3.org/TR/2014/WD-css-gcpm-3-20140513/
string-set プロパティと string 関数が使えるので セクションタイトルをページの右上に常に表示したいなら
<!doctype html>
<meta charset="utf-8" />
<title>title</title>
<style>
@page {
size: A4;
@top-right {
content: string(heading);
}
}
h1 {
string-set: heading content();
}
</style>
<h1>h1</h1>
<p>p</p>
という感じで h1 のスタイルで string-set を指定して heading に h1 タグ内の content を設定
右上のヘッダ部分の content で heading を参照
これでヘッダにセクションタイトルを設定できる
それならドキュメントタイトルを左上に表示にしたければ title タグに同じようなことをすればできるはず
<style>
@page {
size: A4;
@top-left {
content: string(title);
}
@top-right {
content: string(heading);
}
}
title {
string-set: title content();
}
h1 {
string-set: heading content();
}
</style>
これで表示されるかと思ったけど表示されない
title タグは head タグの中だからスタイルの対象外?
調べると head タグの中ではなく display: none の要素は対象外らしい
https://github.com/Kozea/WeasyPrint/issues/473
回避策は head と title タグを display: none じゃなくすることらしい
だけど head タグを block にすると表示対象になるのでその中も表示される
head タグ内の他のタグ(style タグなど)は display: none だから 問題は title タグ自身も表示されること
これを避けるために visibility を hidden にする
それだけだと見えないだけでレイアウトに影響するのでサイズを 0 にする
これで左上にドキュメントタイトルが表示できるようになった
head, head title {
display: block;
visibility: hidden;
width: 0;
height: 0;
}
結構前からある問題みたいだし そろそろ修正されて欲しいけど