Created
December 12, 2020 10:11
-
-
Save zr-tex8r/43090955d778d68528b420c661657a14 to your computer and use it in GitHub Desktop.
Pandoc: Pandocで湯婆婆するLuaフィルタ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- yubaba.lua | |
-- | |
-- @copyright 2020 Takayuki YATO (aka. "ZR") | |
-- GitHub: https://github.com/zr-tex8r | |
-- Twitter: @zr_tex8r | |
-- This program is distributed under the MIT License. | |
-- | |
local filter_name = 'yubaba' | |
---------------------------------------- 設定 | |
-- 湯婆婆処理対象のクラス名 | |
local yubaba_class = 'yubaba' | |
---------------------------------------- 補助 | |
local utils = utils or require 'pandoc.utils' | |
-- 乱数種の設定 | |
math.randomseed(os.time()) | |
--- 名前を1文字に短縮する. | |
-- ※名前が空ならエラー. | |
-- @param name 名前(文字列) | |
-- @return 短縮した名前(文字列) | |
local function compact(name) | |
local ucs = { utf8.codepoint(name, 1, #name) } | |
if #ucs == 0 then -- 名前が空である | |
error("name is empty") | |
end | |
return utf8.char(ucs[math.random(#ucs)]) | |
end | |
--- Pandocオブジェクトならクラス名, それ以外ならLua型名を返す. | |
-- @return 型名(文字列) | |
local function ptype(v) | |
local t = type(v) | |
return t == 'table' and v.t or t | |
end | |
--- 複数のテーブルを連結する. | |
-- @return 結果(テーブル) | |
local function merge(...) | |
local dst, srcs = {}, {...} | |
for i = 1, #srcs do | |
local src = srcs[i] | |
for j = 1, #src do dst[#dst+1] = src[j] end | |
end | |
return dst | |
end | |
--- オブジェクトが湯婆婆処理対象のSpanであるか. | |
-- @return 真偽値 | |
local function is_yubaba_span(el) | |
return ptype(el) == 'Span' and el.classes:includes(yubaba_class) | |
end | |
--- オブジェクトが湯婆婆処理対象のParaであるか. | |
-- @return 真偽値 | |
local function is_yubaba_para(el) | |
-- Paraの内容が"湯婆婆処理対象のSpan"のみであるかを調べる. | |
if ptype(el) == 'Para' and #el.content == 1 then | |
return is_yubaba_span(el.content[1]) | |
end | |
return false | |
end | |
---------------------------------------- フェーズ'main' | |
-- 湯婆婆対象のParaを変換する. | |
--- Paraに対する処理. | |
local function main_Para(el) | |
if is_yubaba_para(el) then -- 湯婆婆対象の場合 | |
local yspan = el.content[1] -- 湯婆婆対象のSpan | |
-- 新しい名前を得る. utils.stringify() は"文字列化"の関数. | |
local newname = compact(utils.stringify(yspan)) | |
-- 変換後の内容を返す. | |
return { -- 複数ブロックを返していることに注意 | |
pandoc.Para { | |
pandoc.Str "「契約書だよ。そこに名前を書きな。」" | |
}, | |
pandoc.BlockQuote { | |
pandoc.Para(yspan.content) -- 元の名前 | |
}, | |
pandoc.Para(merge( | |
{ pandoc.Str "「フン。" }, | |
yspan.content, -- 元の名前 | |
{ | |
pandoc.Str "というのかい。贅沢な名だねえ。」"; | |
pandoc.LineBreak(); | |
pandoc.Str "「今からお前の名前は"; | |
pandoc.Str(newname); -- 新しい名前 | |
pandoc.Str "だ。いいかい、"; | |
pandoc.Str(newname); -- 新しい名前 | |
pandoc.Str "だよ。分かったら返事をするんだ、"; | |
pandoc.Str(newname); -- 新しい名前 | |
pandoc.Str "!」"; | |
} | |
)) | |
} | |
end -- 湯婆婆対象以外は変更しない | |
end | |
---------------------------------------- フェーズ'check' | |
-- 湯婆婆対象のSpanが残っていないことを確認する. | |
-- 残っている場合は"湯婆婆対象のSpanの記述条件"に反しているのでエラー. | |
--- Spanに対する処理. | |
local function check_Span(el) | |
if is_yubaba_span(el) then | |
error("bad yubaba span found") | |
end | |
end | |
---------------------------------------- フィルタ定義 | |
return { | |
{-- フェーズ'main' | |
Para = main_Para; | |
}; | |
{-- フェーズ'check' | |
Span = check_Span; | |
}; | |
} | |
---------------------------------------- おしまい |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
解説→Pandocで湯婆婆