Skip to content

Instantly share code, notes, and snippets.

@zr-tex8r
Created December 12, 2020 10:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zr-tex8r/43090955d778d68528b420c661657a14 to your computer and use it in GitHub Desktop.
Save zr-tex8r/43090955d778d68528b420c661657a14 to your computer and use it in GitHub Desktop.
Pandoc: Pandocで湯婆婆するLuaフィルタ
-- 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;
};
}
---------------------------------------- おしまい
@zr-tex8r
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment