From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.text.pandoc/26910 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: BPJ Newsgroups: gmane.text.pandoc Subject: Re: How to add a `\usepackage` in a Lua filter meant to support LaTeX? Date: Fri, 20 Nov 2020 16:54:21 +0100 Message-ID: <3648902d-0ed0-be10-02c6-e5527d6eaaa4@gmail.com> References: <2e27c210-a276-4319-abd7-c81d5db7f7d7n@googlegroups.com> Reply-To: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------BD8900F0E2F23F110AE4EDCE" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="33524"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 To: pandoc-discuss Original-X-From: pandoc-discuss+bncBCWMVYEK54FRBMON376QKGQETTCYLIY-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Fri Nov 20 16:54:29 2020 Return-path: Envelope-to: gtp-pandoc-discuss@m.gmane-mx.org Original-Received: from mail-wr1-f58.google.com ([209.85.221.58]) by ciao.gmane.io with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kg8k1-0008dE-Dl for gtp-pandoc-discuss@m.gmane-mx.org; Fri, 20 Nov 2020 16:54:29 +0100 Original-Received: by mail-wr1-f58.google.com with SMTP id k1sf3545393wrg.12 for ; Fri, 20 Nov 2020 07:54:29 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1605887669; cv=pass; d=google.com; s=arc-20160816; b=UF45dW/tbLtmEr5fApmC5btg4iNTdBAX8ASFTpMb0ZLMTudSQ2M9iNHkJ8v3HOBQZS 1Vsj4uOsTFRztxsdDo18pEreEL70dELqJqNf9sox+vvnagj7K7bSvh2/0ETThg/jQVxn Fg9dSKibgFMc96/5ARigibglR+zENcEwXL8PZiUdreNuDyWPnlZq0Daaq9n+Rtdh5QBY 4itK6pUo/gzzePjWC6EOsIi9Jz4mZfDUwJFf9t4ms7RKXdAGmgmf9pdUs/2PQXUNZUgh 6wJb6W6IS9/X9Xrft2ZAbi3sHq2nhxTBPG8Gx7/1h0lW42ajgKkBbg4cSwyIFeArazh0 9j+Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to:content-language :in-reply-to:mime-version:user-agent:date:message-id:from:references :to:subject:sender:dkim-signature:dkim-signature; bh=WMWcdjc+bRfYRmYlM0Id4X6VGMRaR1zybfJR0/VOGpo=; b=J5+RKR1I0m310GVe+KKeczSgtzkIcxpZI6OZB0lhmDiiOl9Ur0QBdw5nKID3651qSi IoLaORjNaKb11Nu5EdYUWw0C8a7MIWfW+68ta4qJezjAbuJHYaQ5MpsS4Uw7zIeYopDx 3zqNOImbFfulYqQE3oA7iRvo1nYdPx3JS4F+OllOWPzN188JO2BWWc5M4TA7CfCPZuZh Uo5tVDOf2yOg2iwG1PtlkYpZ8fnDfNWXXJGVepr3Tk90KTG+YtwNOWrbjTq2Rp0exKtm s6sJa16vNdmJLL1TFPTXvOsxI9UHPdfJqRKDkDxmwhW91odfpP0nwAI34drknpo/Y0gA XHnw== ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=jdIUtSn8; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2a00:1450:4864:20::52d as permitted sender) smtp.mailfrom=melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:subject:to:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:list-post:list-help:list-archive:list-subscribe :list-unsubscribe; bh=WMWcdjc+bRfYRmYlM0Id4X6VGMRaR1zybfJR0/VOGpo=; b=mtSZFKABJT5rbviu7+1xqcpOLwXMyG79ku589gAW3U01/sNOz5c32gcotBsRlwgDc5 ykBi2sdxY+HK7St7sjq0AUrQ2+3jpBSt2iDykbPGWy+EAGSauWu+K8avu5kEQJV1v2ui 4CKwy09oJ/nEw4kLfMsBe3anlj6c9d3mOL8Kusw6IXrLpPYEpz+Q46Wh/dT0JjP3mmWb 7A8ivC1Jb1t1zysTOxUj5IYJpym2ndjHexBOF3KDpq36K8Fj6GxrBPSmaFflQO0mdfFn OR9rrQKkoPvmYJyRRvjN4D9fxe5NaaF/cUrY6ay1yGnuGlBgoM6em940lkAObCvY2uhs MMEA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-language:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:list-post:list-help:list-archive:list-subscribe :list-unsubscribe; bh=WMWcdjc+bRfYRmYlM0Id4X6VGMRaR1zybfJR0/VOGpo=; b=NzB026xEuqf1Dphdb1gIEx6G+vQtINiZpbAKaCrhrNV9XpHiU/u1yTuKf6R56M2RMv ekQdksdCfKIH5CHMeB3298CvVz7A6CDicF7DCLOPlnOityOjaidG2yNeHSaov0HqDQVl 4z64xPdtL/x1nIJ/eCSv3Cx+FquizcV/Z4pUw9GDSlPibZXrMNBtMdvJjnJv6rC3fXdV ej7Zp+HMhFZz7yBzoujiJdvetwLJwQT9neZqC2tlTZ5huXM55GnqZ+GbVPkF+yEpl4qE 2H4T0hUlEypnNeYzLu5WkU0QMN45UgMHbGMA70hsQMWxgV9vD87D+7h1HjdwPieDcTsb YRfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:subject:to:references:from:message-id :date:user-agent:mime-version:in-reply-to:content-language :x-original-sender:x-original-authentication-results:reply-to :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post :list-help:list-archive:list-subscribe:list-unsubscribe; bh=WMWcdjc+bRfYRmYlM0Id4X6VGMRaR1zybfJR0/VOGpo=; b=gryAYHaFcuakUfi97/gn89FphhK+Y15cw+Tl4wh0A2KEYKjrqunbMR8r9TMMgtNiLT fjaWCf5YCpw+A8KPuGYbhjtbXmPumMdrAr6PmcxS/OGZ2XX+5wXOgssC6Hz2a2xfBvRj 1aJ4MLSrYfxd5FY2BIGdgbTL7CrwDtkC4ucKmSbjaSHVXzUX9mXzFDr6niDwISavPTpF rBL1IAHf6s7EjbX34gJnwI9a7txUVK081UL51MYsRK8k0neEDFBSnHUWaMy1HOuWG2Qq G5epb7LKtSWyEvj3G7XwqM+tl9a2FXr9FIt78y3PTSfCULKqUE6kZO6s5CkMqF9X1VXT Original-Sender: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org X-Gm-Message-State: AOAM533sYiWY9ZDAlVgDG1Jy6vAA5/aZOEfu1BjKW+/xL9fvBqKTB9K0 4COSKbdZkaLVMANpeIkg+EY= X-Google-Smtp-Source: ABdhPJzM/S1qJYrjyubmjmJ/xyj+0/PY1mSycu9HO0wwRHPEwfHM5+MsDoPyBHMd0U0zt8WD29WJUQ== X-Received: by 2002:a1c:c343:: with SMTP id t64mr11067778wmf.140.1605887669102; Fri, 20 Nov 2020 07:54:29 -0800 (PST) X-BeenThere: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Original-Received: by 2002:adf:f70d:: with SMTP id r13ls4283281wrp.1.gmail; Fri, 20 Nov 2020 07:54:25 -0800 (PST) X-Received: by 2002:adf:fcc8:: with SMTP id f8mr16817206wrs.331.1605887664969; Fri, 20 Nov 2020 07:54:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605887664; cv=none; d=google.com; s=arc-20160816; b=Ndd1SRCn6hsXHgtMLrR9UBa8djhdFe75pFRbF0e2NpQgeTQ1l6F3RdG4hAMjPtrVc+ MVaGX5qqarToh+OM7PWhqHl2u4GnxWOZBa9M6LVUWYDT1c4s5VRMcY3Y/fRbwBHgwb9g qRGELxFsS/qb2z8xb2WcQiHiy9drJzbd/1MCMI0WKQTXMs/JXe+7ui6J7ZCW2MPkLzpF 9JQsSJ6hrA8fqcXXBCiEGDBw8p79GriUDx3S/3YCHAvfQNtaTlo53Tp1VHqBgz+cMKqc 0k7uocefXWUfd0Lnrv9jBDzn/jh8O5ADtEl0gf/oPpPvs5mcultpY5Xul2ZcHGx7TSpl WAsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:to:subject:dkim-signature; bh=FZ6145dgQbLqLOEx42pLgArABn+HTIUBowTL0pCG93I=; b=iAjjuhUwt5KHR5+E5ULlauP0ji2vFYCTjkuMHorTVd0akStw1kNKmO5h9v1UDw3tEs DC28usSy/tfIKh3MZf0vDr6HtuhG26O2TXgeoU+qoMPABUtZ/JOb5AIdKt4JF+Ee3DS2 X3O4KTohKxwXrvA6riCp8cnK3Nmm8xaMsA1OQyYKwV6qGtnis82X8hpKs7WgLENfoOZ+ lNtpcF+UbyQD9MkJDIjo9k5xKR7KEkJCiMN1w/puEbBCaKNAvQ/Zw0rWShqTGO+EMvxa L7bnSrPPy5Ywu6J7/7TWm5lJPnDVe5rrgkxdHQBaUnsbluaDcezklcFL6CVtGGuft2iS lSUw== ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=jdIUtSn8; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2a00:1450:4864:20::52d as permitted sender) smtp.mailfrom=melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Original-Received: from mail-ed1-x52d.google.com (mail-ed1-x52d.google.com. [2a00:1450:4864:20::52d]) by gmr-mx.google.com with ESMTPS id z17si104784wrh.2.2020.11.20.07.54.24 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 20 Nov 2020 07:54:24 -0800 (PST) Received-SPF: pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2a00:1450:4864:20::52d as permitted sender) client-ip=2a00:1450:4864:20::52d; Original-Received: by mail-ed1-x52d.google.com with SMTP id d18so10009343edt.7 for ; Fri, 20 Nov 2020 07:54:24 -0800 (PST) X-Received: by 2002:a05:6402:1a58:: with SMTP id bf24mr34636444edb.191.1605887664459; Fri, 20 Nov 2020 07:54:24 -0800 (PST) Original-Received: from [192.168.1.122] (user177.77-105-231.netatonce.net. [77.105.231.177]) by smtp.gmail.com with ESMTPSA id bg4sm1310762ejb.24.2020.11.20.07.54.22 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 20 Nov 2020 07:54:22 -0800 (PST) In-Reply-To: <2e27c210-a276-4319-abd7-c81d5db7f7d7n-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> Content-Language: en-US X-Original-Sender: melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=jdIUtSn8; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2a00:1450:4864:20::52d as permitted sender) smtp.mailfrom=melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Precedence: list Mailing-list: list pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org; contact pandoc-discuss+owners-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org List-ID: X-Google-Group-Id: 1007024079513 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Xref: news.gmane.io gmane.text.pandoc:26910 Archived-At: This is a multi-part message in MIME format. --------------BD8900F0E2F23F110AE4EDCE Content-Type: text/plain; charset="UTF-8"; format=flowed On 2020-11-19 20:27, Norman Ramsey wrote: > I've got a Lua filter that is meant to render certain document elements in > a `boxedminipage` environment. To accomplish this feat, I give the element > in a suitable `div`, and a Lua filter inserts the LaTeX environment. The > document itself remains universal, but the Lua filter is resolutely > intended for LaTeX. > > The filter adds a raw `\usepackage{boxedminipage2e}` to the > `header-includes` of the metadata, but unfortunately when `-V > header-includes=...` appears on the command line, it takes precedence and > the document metadata is ignored. However you can, if the filter appends any includes done in the filter to any existing meta.header-includes list combine it with header-includes defined in a *metadata file* via option --metadata-file=FILE or metadadata-files: in a defaults file using the usual idiom: `````````yaml header-includes: - | ````{=latex} \usepackage{relsize} ```` ````````` Alternatively you may even have a filter collect files and inject their contents into the metadata header includes. Two proof-of-concept filters attached: 1. `inject-includes.lua` shows how you may inject includes dynamically in a filter, either creating the meta.header-includes list or appending them to an existing one. 2. `inject-includes-files.lua` shows how you may inject the contents of a directory `header-includes` into the meta.header-includes list and thus get the best of both worlds! :-) -- You received this message because you are subscribed to the Google Groups "pandoc-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to pandoc-discuss+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msgid/pandoc-discuss/3648902d-0ed0-be10-02c6-e5527d6eaaa4%40gmail.com. --------------BD8900F0E2F23F110AE4EDCE Content-Type: text/x-lua; charset=UTF-8; name="inject-includes.lua" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="inject-includes.lua" -- inject-includes.lua -- A proof-of-concept Pandoc filter showing how you may create -- header-includes from inside a filter. -- -- NOTE: this only works if you do *not* use the -H/--include-in-header -- option on the command line or include-in-header: in a defaults file. -- However you can, since the filter appends any includes done in -- the filter to any existing meta.header-includes list combine it with -- header-includes defined in a *metadata file* via -- option --metadata-file=FILE or metadadata-files: in a defaults file -- using the usual idiom: -- -- header-includes: -- - | -- ````{=latex} -- \usepackage{relsize} -- ```` local includes = pandoc.MetaList{} local function inject_include (include, format) -- Fall back to the current output format as raw format -- NOTE: this is a bit risky if you do injects for multiple -- output formats in the same filter! format = format or FORMAT -- Do the actual header include injection includes[#includes+1] = pandoc.MetaBlocks{pandoc.RawBlock(format, include)} end -- If you know you are going to need certain header includes inject them here inject_include( '\\usepackage[margins=raggedright]{floatrow}', 'latex' ) local function add_includes (meta) -- Get an alias so we don't need to type the long name local hinc = 'header-includes' if not meta[hinc] then meta[hinc] = includes else -- Make sure meta.header-includes is a MetaList -- or bail out if it is not. if 'table' ~= type(meta[hinc]) or 'MetaList' ~= meta[hinc].tag then error "Expected meta.header-includes to be list" end meta[hinc]:extend(includes) end return meta end -- If you need to inject includes dynamically do e.g. this: local use_relsize = false -- Reusable template. -- We use `\textlarger` but text will be smaller if number is negative, -- e.g. `\textlarger[-1]` == `\textsmaller[1]`! local relsize_format = '\\textlarger[%d]' local function do_relsize (span) local size = span.attributes.rs -- I like short class/attr names! :-) if not size then return nil end if not use_relsize then inject_include('\\usepackage{relsize}', 'latex') use_relsize = true end size = pandoc.RawInline('latex',relsize_format:format(size)) return {size,span} -- curlies included by pandoc! end return { { Span = do_relsize }, { Meta = add_includes }, } --------------BD8900F0E2F23F110AE4EDCE Content-Type: text/x-lua; charset=UTF-8; name="inject-includes-files.lua" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="inject-includes-files.lua" -- inject-includes.lua -- A proof-of-concept Pandoc filter showing how you may collect -- header-include files' contents and inject them into document -- metadata from inside a filter. -- -- This is useful if you want to both include metadata from files -- *and* inject header-includes from filters, since if you use -- the -H/--include-in-header option or `include-in-header:` in a -- defaults file meta.header-includes will be ignored. -- -- The workaround is to let a filter locate header-includes files -- from a directory `header-includes` and/or files with names of -- the form `header-include.EXT in the working directory -- and inject their contents into meta.header-includes. -- Pandoc's builtin mechanisms for header-includes files -- must *not* be used! -- -- Files are only included if their extension agrees with the -- current output format. An extension agrees when it is -- identical to pandoc's output format name or is included in -- a table mapping extensions to "agreeing" formats. -- See `local extension` in the filter code below. local function qw (str,pat) pat = tostring(pat or '%S+') str = tostring(str) local lst = {} for s in str:gmatch(pat) do lst[#lst+1] = s end return lst end local function set (list) if 'table' ~= type(list) then list = qw(list) end local set = {} for _,v in ipairs(list) do set[v] = true end return set end local extension = { -- Maps extensions to formats which should have files -- with that extension included. ltx = set"latex beamer", tex = set"latex beamer", html = set"html html5 html4 epub", -- still more? } local function get_includes (format) -- Fall back to the current output format as raw format format = format or FORMAT local includes = pandoc.MetaList{} local includes_dirs = { { dir = '.', pat = '^header-include%.(%w+)$', }, { dir = 'header-includes', pat = '^..-%.(%w+)$', }, } for _,d in ipairs(includes_dirs) do -- Leave to Windows users to figure out how -- to do this on windows. pandoc.system.os -- could be consulted to determine the os local ls = pandoc.pipe("ls",{d.dir},"") -- Seems ls output is returned one line per item for _,f in ipairs(qw(ls,'[^\n]+')) do ext = f:match(d.pat) if ext and(extension[ext] and extension[ext][format]) or(ext == format) then f = d.dir .. '/' .. f local handle = assert( io.open(f), "Couldn't open " .. f ) local include = handle:read'a' handle:close() if "" ~= include then includes[#includes+1] = pandoc.MetaBlocks{ pandoc.RawBlock(format, include) } end end end end if #includes > 0 then return includes end return nil end function Meta (meta) local includes = get_includes(FORMAT) if not includes then return nil end -- Get an alias so we don't need to type the long name local hinc = 'header-includes' if not meta[hinc] then meta[hinc] = includes else -- Make sure meta.header-includes is a MetaList -- or bail out if it is not. if 'table' ~= type(meta[hinc]) or 'MetaList' ~= meta[hinc].tag then error "Expected meta.header-includes to be list" end meta[hinc]:extend(includes) end return meta end --------------BD8900F0E2F23F110AE4EDCE--