From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.text.pandoc/32824 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: BPJ Newsgroups: gmane.text.pandoc Subject: Re: Inserting attributes into elements Date: Thu, 15 Jun 2023 15:00:39 +0200 Message-ID: References: <76a72c07-6699-d243-ae20-64808682ec9e@meddatainc.com> <90C7A30F-C0FA-49D8-B0CD-6521B58113F1@meddatainc.com> <0a6aa41a-fe72-a1e8-2630-ec6070c0bbb3@meddatainc.com> <74253f39-02db-dc2e-2ae1-9d27aaab82ea@meddatainc.com> <61724767-ada0-133f-6751-5884c7460a25@meddatainc.com> <37d8c191-388e-164e-6955-9014b4f0a4a0@meddatainc.com> Reply-To: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="00000000000077056305fe2aa836" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34560"; mail-complaints-to="usenet@ciao.gmane.io" To: pandoc-discuss Original-X-From: pandoc-discuss+bncBCWMVYEK54FRBBUXVSSAMGQEH5UMTCQ-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Thu Jun 15 15:01:00 2023 Return-path: Envelope-to: gtp-pandoc-discuss@m.gmane-mx.org Original-Received: from mail-pj1-f58.google.com ([209.85.216.58]) by ciao.gmane.io with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1q9max-0008mN-69 for gtp-pandoc-discuss@m.gmane-mx.org; Thu, 15 Jun 2023 15:00:59 +0200 Original-Received: by mail-pj1-f58.google.com with SMTP id 98e67ed59e1d1-25df07d4d17sf981909a91.3 for ; Thu, 15 Jun 2023 06:00:59 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1686834058; cv=pass; d=google.com; s=arc-20160816; b=QAIxpfR5VwTJ2tUcCM668ecUUVhiCR1oV0YsTaLTXp718S6nHGKmnjnr4/IUgEXf/d 8rYzcsptCcq4gm9XYYeyZP82Sxl7Rk835OSpVETE4PGgeY7mr7NL0KqriAUMtOsCKLIs PlhfAOY/zxp1L4/cFkODSqvA4zcA1IOKY2sVLcHwRE0PuZMs4GPhJxhufvRQl6Yxtazk Iyz90w/BmN5Y7b1PR3yyXsCOvC1042jsHLcXghop3Zi0ya+4mB/zaui0M1g2zNszcFtV F0B+m8Hq98nB0EhEDtMy1cVN8p01BzC72GTggmPNMLPwIKL0uKRGEuuCrzaB+pykaINC tpGA== 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:to:subject:message-id:date :from:in-reply-to:references:mime-version:sender:dkim-signature :dkim-signature; bh=lMg13gT7i3F/0MvnHMwpq8ZLCX/yUXi1uVN6NOi+ITE=; b=ydtNUp7FX+iMezB+kW/gLXbm9o2jjxQucyltTxU0+phlqDdeLWlSbdg46pthuGQUpC K1nTGClTmBAsXM8C/Fat5t5nog24o+v+HfRIWzzj+qS/+kc8DO2sORRqGdt71/EocazU arcd1et34wLyU08aUTuEghCj2BS30u4K3rTOMY3IGhC+xoOKVmUqE9yPbFhpo8e7a5pv nFDFrLlMmtyvrig9FwLslKgojmqRdbPdsIi2+7FjEOlyyrP/uKnc0j/SEHJr2roKVvgZ aNjhJw6OlxEvfg+eKmvxO3Yfxee7QIWbLLxU78eZnQzF+fukBGiWaa9TmEB7/EgjT5+n bZlw== ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=CpmQCdtE; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2607:f8b0:4864:20::1132 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=20221208; t=1686834058; x=1689426058; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:to:subject :message-id:date:from:in-reply-to:references:mime-version:sender :from:to:cc:subject:date:message-id:reply-to; bh=lMg13gT7i3F/0MvnHMwpq8ZLCX/yUXi1uVN6NOi+ITE=; b=mRqo9rM3rXAqmAMzP0c2EeVExWSEDGoegPHh/fyI2Flzei4rj+nSoe/ohtnU1NVuNy B3TmLPZzzHpID6i2dUhjjKQ/kVuSLUcUGBMd+Lyuk12ljLgYtqfTWsb7hJ9ttOmsUwwc GzrVxGyrvkXBLyCdlsgJ+m9qHVhE7aUxqJTx86Yl9uZl2S6PiAamcDJ3U0dSTj4Bf4HS +uhMlWBE2+DMY1xZoQKvRv29h9/Vz7Sd7JvZlU986d9Ktjc572sl0hdxY43qUPdqRVWM +1Xbr1GU/oogdAyWaVNckyqvwduxym8MmsZeqPnMHlBEF4u0BJVildj7cbxFjvzkhtV/ DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1686834058; x=1689426058; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:to:subject :message-id:date:from:in-reply-to:references:mime-version:from:to:cc :subject:date:message-id:reply-to; bh=lMg13gT7i3F/0MvnHMwpq8ZLCX/yUXi1uVN6NOi+ITE=; b=syoNtH3GDksEVYNF/8QD4BsGmMjVz0mM/KgTeByzYN/jp7sdTo8wcrr/MtIHeEJeYk mCUUe49RfHNVu+JrX2QpO6Cyn+3WqSspBhuqinslLzYsbsNkL9SURTBbURKhf5KJQaXt zm+POH2lrhpuMJGCtyU0TYWKNBcZeX8S1xwUTwVGVHSN2SH9IijVwjuegGCYBuRn7KGY J1oP5aOs2S6AiCKykzu1HoEW08UZ8aKKsAdWcvi6yEdNKV9ChU6F03eGJyO4fk3lrr8c r14NOWILqMvF/aoz0G9vQBf+M8pgDNHE9DnmYbdqf/7f/8CnYfbH8isAl0VTyKmdrqO6 pcCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686834058; x=1689426058; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence:reply-to :x-original-authentication-results:x-original-sender:to:subject :message-id:date:from:in-reply-to:references:mime-version :x-beenthere:x-gm-message-state:sender:from:to:cc:subject:date :message-id:reply-to; bh=lMg13gT7i3F/0MvnHMwpq8ZLCX/yUXi1uVN6NOi+ITE=; b=enav80ylQ85oHLxHL99LF5q/z6AC4GMlYovwOmaJF5qeG4UCs2ot5AZHpok4Fhv+JH pywcyWio1qUilDZncMuqAjVXwOW8qDT1hXuQ2WcXfCOmtQMGnem7hErdsrV0MVhxYagJ qnZNnk9gV7xV4iPA/xAJUkqpveVmyDRL5ZRfqbpiyVQDRjhFTgmLRy7uiz9ESusDjBDY BMl82pCZ82v3VMiYfi27ujf9JXFZtfxUrHuAJtRFYATPshD+QnQbHqQHGfW+Cx0/+AiN 05yfcq Original-Sender: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org X-Gm-Message-State: AC+VfDyWVrkCbRdFog2xi7srIDQoTFoGTJGlfUz4m7TXY/M07e/vdiD7 b6qvcjgTpSJDbd/BJeXdExU= X-Google-Smtp-Source: ACHHUZ718bY7LpPjnszy/uD5quuCmfu3CVfwNSH7EP7pC06/lbQuVzIR8G88IqBhdL6hC2WdlvLOow== X-Received: by 2002:a17:90a:d915:b0:25e:a0a7:7d48 with SMTP id c21-20020a17090ad91500b0025ea0a77d48mr656661pjv.14.1686834057406; Thu, 15 Jun 2023 06:00:57 -0700 (PDT) X-BeenThere: pandoc-discuss-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Original-Received: by 2002:a17:90b:4b52:b0:255:85a6:3d07 with SMTP id mi18-20020a17090b4b5200b0025585a63d07ls1940194pjb.1.-pod-prod-05-us; Thu, 15 Jun 2023 06:00:53 -0700 (PDT) X-Received: by 2002:a17:903:187:b0:1b3:f8db:6f0e with SMTP id z7-20020a170903018700b001b3f8db6f0emr6072900plg.43.1686834053265; Thu, 15 Jun 2023 06:00:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686834053; cv=none; d=google.com; s=arc-20160816; b=uyzXOob1FEzKCkOmorWTWo2Qjzg9q8uki0B8Q6XUQgp4BN7OJkxH3f/wpDcgtK6N3I QNhpvdQgdeQZ4RUYGRQdk3xcumF2MyfBU7aBKQATzuRxphD4+0W40uPS1ziC/sF4Cd1I C29afsJfolhKzHxXL4kBdtb36HOn3jAQ2xZ0wB7bYhNNQdxKOvokLNNIUdS/gSK+iyJw QVmv4MuejuquU0wO7hn++vNqbEv8sOG9L7V7fWdUUCkEfhOFmF3/GzBaVSm6oBcdWYeV oukdMQ6SVIbWtDobb8gViuDz9Wp8soWqN/LoYoTzNa7554ixlgIztIZNdoeqliKDBTNo UVGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=rhMPfRyOEkaRsXCzR54BWF4ih6NaqRZ0G/WizYlkcDU=; b=Ln3lyT4OzvNG3DS2hhZ/+ZXYf6YBKhLLGBfAW/jodjMj7rWrC5p2wGQyKEOkedj3GT OuGStXbkoUyTn0yNtq0tP8nt6UqsW8R8GSBZLt1FUEWPm6h+SYPy4tvcMvdvtqMXmCXQ LnD/TW3uRwBCbrF842/BT4uAaiwzvfGKPrPvWux14m2bIlWZpy7unR0OAEMC06AevHLm FApYrGLMT1dW+XgGhzlrdq13Cht2ITzitYUnvqgCFwfj1hjK5HSHsf4ywufcV0Pl+MKJ 8qXtcVDPQ20mK8NZZ/xZccgcdcA+X0OOV0sOybUrv8iSh4Q1eeD4oQFKF1HNpHQFWvGf +1OA== ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=CpmQCdtE; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2607:f8b0:4864:20::1132 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-yw1-x1132.google.com (mail-yw1-x1132.google.com. [2607:f8b0:4864:20::1132]) by gmr-mx.google.com with ESMTPS id c15-20020a170902b68f00b001a1a9a5e546si914084pls.9.2023.06.15.06.00.53 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 15 Jun 2023 06:00:53 -0700 (PDT) Received-SPF: pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2607:f8b0:4864:20::1132 as permitted sender) client-ip=2607:f8b0:4864:20::1132; Original-Received: by mail-yw1-x1132.google.com with SMTP id 00721157ae682-56cf00a04e5so19520367b3.0 for ; Thu, 15 Jun 2023 06:00:53 -0700 (PDT) X-Received: by 2002:a25:f512:0:b0:bc6:3fbc:1180 with SMTP id a18-20020a25f512000000b00bc63fbc1180mr4820547ybe.41.1686834052005; Thu, 15 Jun 2023 06:00:52 -0700 (PDT) In-Reply-To: <37d8c191-388e-164e-6955-9014b4f0a4a0-FcZObrvlYduBUy7/sJONFg@public.gmane.org> X-Original-Sender: melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=CpmQCdtE; spf=pass (google.com: domain of melroch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org designates 2607:f8b0:4864:20::1132 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:32824 Archived-At: --00000000000077056305fe2aa836 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Den tors 15 juni 2023 03:20H skrev: > On 06/14/2023 01:30 PM, BPJ wrote: > > > > Pandoc's document module used to not support attributes at all. IIRC > attributes were first introduced for fenced code blocks, then extended to > inline code. Spans and divs (in the Pandoc sense) were introduced > specifically to provide containers for arbitrary content to which > attributes can be attached. At the same time (IIRC) attributes were > extended to headings ("Header"), links and images. It was decided not to > extend attributes to other elements as that would entail huge changes to > the code base. Later when Pandoc's table model was changed the new table > model included attributes. > > > > Code needs attributes to allow to attach highlighting information to it= , > and headings and images need them too for various reasons, and links > probably came along for the ride together with images. Normally divs and > spans are enough for all other cases, because in regular CSS in an extern= al > file or embedded in the `` of an HTML document you can use a child > selector, e.g. in Markdown you type > > > > ``````markdown > > :::class > > **** > > ::: > > `````` > > > > and then you style the rule with > > > > ``````css > > div.class hr { ... } > > `````` > > > > Your imposed limitation of not being able to use external CSS creates > problems which most users simply don't have. For the horizontal rule case > you can use a raw block to insert the HTML directly, if you are not going > to generate other formats from the source: > > > > ``````markdown > > Para before. > > > > ```{=3Dhtml} > >
> > ``` > > > > Para after > > `````` > > > > You can also use a filter to do things like this: > > > > ``````lua > > local hr_filter =3D { > > HorizontalRule =3D function() > > return pandoc.RawBlock('html', '
') > > end > > } > > function Div(div) > > if div.classes:includes('class') then > > return div:walk(hr_filter).content > > end > > end > > `````` > > > > > > I sometimes post-process HTML generated by pandoc with with Mojo::Dom < > https://metacpan.org/pod/Mojo::DOM> to transfer attributes from wrapping > divs/spans to contained elements and remove the wrapper, or just to set > attributes to elements contained in wrappers. The API makes such changes > very easy. You basically find elements in an HTML document with CSS > selectors, then loop through the found elements and change them in-place > with Perl code. Adding/removing/changing attributes is very easy: you jus= t > treat the element object as if it is a hash (associative array) reference > containing the attributes! Then when you are done you print the document > object to a file or stdout. > > > Thank you for the explanation. I did resort to creating the
in > the filter. > > Now another problem - I have multiple images in my markdown document and = a >
tag pair gets added around the which is fine. > > However, while processing the
block I want to make changes to th= e > default style attribute for some of the images. Using the logging > module I find e.g.: > > (#) figure Figure { > attr: Attr { > attributes: AttributeList { > style: "margin: 0px;" > } > classes: List {} > identifier: "" > } > caption: { > long: Blocks {} > } > content: Blocks[1] { > [1] Plain { > content: Inlines[1] { > [1] Image { > attr: Attr { > attributes: AttributeList {} > classes: List {} > identifier: "" > } > caption: Inlines[1] { > [1] Str "whatever" > } > src: "https://www.somedomain.tld/images/someimage.jpg" > title: "" > } > } > } > } > } > > > and if look at the logging output for the Image I find: > > #) image Image { > attr: Attr { > attributes: AttributeList { > style: "height: auto; width: 100%; object-fit: contain;" > } > classes: List {} > identifier: "" > } > caption: Inlines[1] { > [1] Str "whatever" > } > src: "https://www.somedomain.tld/images/someimage.jpg" > title: "" > } > > While processing the Figure element in the filter, I want to change the > style attributes for the Image listed above. They show up correctly in th= e > logging module output for Image above but the logging output for Figure > shows an empty list. > I=E2=80=99m not quite sure what you mean but here are basically two ways to= affect only elements inside another element of a certain kind (with a certain tag)= : A. If you want to do something with all Image elements inside any Figure element you can use a local filter which you apply only to the Figure element. This is done by calling the `:walk(inner_filter)` method on the parent/ancestor element. Some things to keep in mind: a) The `inner_filter` is a table where the keys are element tag names and each value are filter functions to apply to descendants with that tag. b) The `:walk` method does _not_ change the element it is called on. Rather it returns a =E2=80=9Ccopy=E2=80=9D with any modifications applied. = Thus you have to assign the return value of `?walk` to a variable, or return the return value of `:walk` from the outer filter function in turn. This again can take two forms: 1. If the action of the inner filter function does not access the parent/ancestor element in any way it is probably more efficient (and less cluttered) to define the inner filter only once outside the outer filter function: ```lua -- Define static "inner" filter once local fig_img_filter =3D { Image =3D function(img) -- Do something with Image img.attributes.style =3D 'border: 0.2rem solid black' return img end } -- Main filter function function Figure(fig) -- Apply "inner" filter to images inside the Figure return fig:walk(fig_img_filter) end ``` 2. If on the other hand the inner filter function needs to access the parent/ancestor element you need to define the inner filter inside the outer filter function where the parent is in scope: ```lua function Div(div) -- Test condition on div if div.classes:includes('foo') then -- Apply dynamic filter to nested links return div:walk({ Link =3D function(lnk) -- Test condition on link if lnk.classes:includes('bar') then -- Copy something from div lnk.attributes.baz =3D div.attributes.zip else -- Copy something else from div lnk.attributes.baz =3D div.attributes.zap end return lnk end }).content -- Div is not needed anymore so replace it with its content end end ``` This also illustrates the common situation where a Div or Span is only used to tell the filter what to do to elements inside it. In this case the Div is no longer needed when you have applied the changes to the elements inside it, so rather than returning the Div you return only what is inside it. B. In case you want to do something only with specific descendants of an element you have to walk/check the children at each level manually. Some things to remember: a) You need to check that any child exist separately before accessing its properties, because trying to access properties on a non-existing value is a fatal error. b) Don=E2=80=99t forget to reassign any elements which you have change= d to the right place in the structure or the change may not take effect. It=E2=80=99= s not all that clear when it is needed so it=E2=80=99s safer to do it always. Here is a more explicit version (with more comments and some extras :-) of my filter for conditionally stripping the Figure around an Image: ```lua function Figure(fig) -- First check that we have exactly one child... if 1 =3D=3D #fig.content then local child =3D fig.content[1] -- ...then check that the child is a Plain... if 'Plain' =3D=3D child.tag then -- ...then check that there is exactly one grandchild... if 1 =3D=3D #child.content then local grandchild =3D child.content[1] -- ...and that the grandchild is an Image. if 'Image' =3D=3D grandchild.tag then -- Bingo! -- Now do we want it to be a figure? if grandchild.classes:includes('fig') then grandchild.attributes.style =3D style_for_img_in_fig -- Put grandchild back child.content[1] =3D grandchild -- Put child back fig.content[1] =3D child fig.attributes.style =3D style_for_figs -- Done with figure return fig end -- else if a standalone image grandchild.attributes.style =3D style_for_img -- Don't want the fig so return the image! return granchild end end end end -- If not all the conditions hold return nil end ``` (Note: the `style_for_*` variables aren=E2=80=99t actually defined in t= his code; they are just placeholders for some strings!) > I thought > print(pandoc.utils.stringify(el.content[1].content[1].attr.attributes)) > would give me the attributes but it does not. > `pandoc.utils.stringify` concatenates and returns the Str element values in its argument, which must be an element object. The attributes of an element don't meet any of those two descriptions, but they are an object with custom stringification (in the Lua sense) so you can just say `print(element.attributes)` to inspect them. > Could this be a bug? > No. > -- > 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/37d8c191-388e-164e-6955-= 9014b4f0a4a0%40meddatainc.com > . > --=20 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 e= mail 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/CADAJKhBjJTZki4np%3DoSfbbcmtBjEahCU4440tRfOh_6TMzSAYw%40mail= .gmail.com. --00000000000077056305fe2aa836 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Den tors 15 juni 2023 03:20H <agents-FcZObrvlYduBUy7/sJONFg@public.gmane.org> skrev:
On 06/14/2023 01:30 PM, BPJ wrote:
>
> Pandoc's document module used to not support attributes at all. II= RC attributes were first introduced for fenced code blocks, then extended t= o inline code. Spans and divs (in the Pandoc sense) were introduced specifi= cally to provide containers for arbitrary content to which attributes can b= e attached. At the same time (IIRC) attributes were extended to headings (&= quot;Header"), links and images. It was decided not to extend attribut= es to other elements as that would entail huge changes to the code base. La= ter when Pandoc's table model was changed the new table model included = attributes.
>
> Code needs attributes to allow to attach highlighting information to i= t, and headings and images need them too for various reasons, and links pro= bably came along for the ride together with images. Normally divs and spans= are enough for all other cases, because in regular CSS in an external file= or embedded in the `<head>` of an HTML document you can use a child = selector, e.g. in Markdown you type
>
> ``````markdown
> :::class
> ****
> :::
> ``````
>
> and then you style the rule with
>
> ``````css
> div.class hr { ... }
> ``````
>
> Your imposed limitation of not being able to use external CSS creates = problems which most users simply don't have. For the horizontal rule ca= se you can use a raw block to insert the HTML directly, if you are not goin= g to generate other formats from the source:
>
> ``````markdown
> Para before.
>
> ```{=3Dhtml}
> <hr style=3D"...">
> ```
>
> Para after
> ``````
>
> You can also use a filter to do things like this:
>
> ``````lua
> local hr_filter =3D {
> =C2=A0 HorizontalRule =3D function()
> =C2=A0 =C2=A0 return pandoc.RawBlock('html', '<hr style= =3D"...">')
> =C2=A0 end
> }
> function Div(div)
> =C2=A0 if div.classes:includes('class') then
> =C2=A0 =C2=A0 return div:walk(hr_filter).content
> =C2=A0 end
> end
> ``````
> =C2=A0=C2=A0
>
> I sometimes post-process HTML generated by pandoc with with Mojo::Dom = <https://metacpan.org/pod/Mojo::DOM> to trans= fer attributes from wrapping divs/spans to contained elements and remove th= e wrapper, or just to set attributes to elements contained in wrappers. The= API makes such changes very easy. You basically find elements in an HTML d= ocument with CSS selectors, then loop through the found elements and change= them in-place with Perl code. Adding/removing/changing attributes is very = easy: you just treat the element object as if it is a hash (associative arr= ay) reference containing the attributes! Then when you are done you print t= he document object to a file or stdout.
>
Thank you for the explanation. I did resort to creating the <hr ... />= ; in the filter.

Now another problem - I have multiple images in my markdown document and a = <figure></figure> tag pair gets added around the <image> = which is fine.

However, while processing the <figure> block I want to make changes t= o the default style attribute <image> for some of the images. Using t= he logging module I find e.g.:

(#) figure Figure {
=C2=A0 attr: Attr {
=C2=A0=C2=A0=C2=A0 attributes: AttributeList {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 style: "margin: 0px;"
=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0 classes: List {}
=C2=A0=C2=A0=C2=A0 identifier: ""
=C2=A0 }
=C2=A0 caption: {
=C2=A0=C2=A0=C2=A0 long: Blocks {}
=C2=A0 }
=C2=A0 content: Blocks[1] {
=C2=A0=C2=A0=C2=A0 [1] Plain {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 content: Inlines[1] {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 [1] Image {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 attr: Attr {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 attribut= es: AttributeList {}
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 classes:= List {}
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 identifi= er: ""
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 caption: Inlines[1] = {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 [1] Str = "whatever"
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 src: "https://www.somedomain.tld/images/someimage.jpg"
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 title: ""<= br> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0 }
=C2=A0 }
}


and if look at the logging output for the Image I find:

#) image Image {
=C2=A0 attr: Attr {
=C2=A0=C2=A0=C2=A0 attributes: AttributeList {
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 style: "height: auto; width: 100%; obje= ct-fit: contain;"
=C2=A0=C2=A0=C2=A0 }
=C2=A0=C2=A0=C2=A0 classes: List {}
=C2=A0=C2=A0=C2=A0 identifier: ""
=C2=A0 }
=C2=A0 caption: Inlines[1] {
=C2=A0=C2=A0=C2=A0 [1] Str "whatever"
=C2=A0 }
=C2=A0 src: "
https://www.somedomain.t= ld/images/someimage.jpg"
=C2=A0 title: ""
}

While processing the Figure element in the filter, I want to change the sty= le attributes for the Image listed above. They show up correctly in the log= ging module output for Image above but the logging output for Figure shows = an empty list.



I=E2=80=99m not quite sure what you mean but here are basicall= y two ways to affect only elements inside another element of a certain kind= (with a certain tag):

A= .=C2=A0 If you want to do something with all Image elements inside any Figu= re element you can use a local filter which you apply only to the Figure el= ement. This is done by calling the `:walk(inner_filter)` method on the pare= nt/ancestor element.

=C2= =A0 =C2=A0 Some things to keep in mind:

=C2=A0 =C2=A0 a)=C2=A0 The `inner_filter` is a table where = the keys are element tag names and each value are filter functions to apply= to descendants with that tag.
=C2=A0 =C2=A0 b)=C2= =A0 The `:walk` method does _not_ change the element it is called on.=C2=A0= Rather it returns a =E2=80=9Ccopy=E2=80=9D with any modifications applied.= Thus you have to assign the return value of `?walk` to a variable, or retu= rn the return value of `:walk` from the outer filter function in turn.

=C2=A0 =C2=A0 This again can= take two forms:

=C2=A0 = =C2=A0 1.=C2=A0 If the action of the inner filter function does not access = the parent/ancestor element in any way it is probably more efficient (and l= ess cluttered) to define the inner filter only once outside the outer filte= r function:

=C2=A0 =C2= =A0 =C2=A0 =C2=A0 ```lua
=C2=A0 =C2=A0 =C2=A0 =C2=A0= -- Define static "inner" filter once
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 local fig_img_filter =3D {
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Image =3D function(img)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Do something with Image=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 img.attri= butes.style =3D 'border: 0.2rem solid black'
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return img
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 }

=C2= =A0 =C2=A0 =C2=A0 =C2=A0 -- Main filter function
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 function Figure(fig)
=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Apply "inner" filter to images in= side the Figure
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 r= eturn fig:walk(fig_img_filter)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ```

=C2=A0 =C2=A0 2.=C2=A0 If on the = other hand the inner filter function needs to access the parent/ancestor el= ement you need to define the inner filter inside the outer filter function = where the parent is in scope:

=C2=A0 =C2=A0 =C2=A0 =C2=A0 ```lua
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 function Div(div)
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 -- Test condition on div
=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 if div.classes:includes('foo') then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Apply dyn= amic filter to nested links
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 return div:walk({
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Link =3D function(lnk)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Test condi= tion on link
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 if lnk.classes:includes('bar') then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 --= Copy something from div
=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lnk.attributes.baz =3D div.attributes.z= ip
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 else
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 -- Copy something else from div
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 lnk.att= ributes.baz =3D div.attributes.zap
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return lnk
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }).content
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Div is not needed = anymore so replace it with its content
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ```

=C2=A0 =C2=A0 =C2=A0 =C2=A0 This als= o illustrates the common situation where a Div or Span is only used to tell= the filter what to do to elements inside it. In this case the Div is no lo= nger needed when you have applied the changes to the elements inside it, so= rather than returning the Div you return only what is inside it.

B.=C2=A0 In case you want to do s= omething only with specific descendants of an element you have to walk/chec= k the children at each level manually.

=C2=A0 =C2=A0 Some things to remember:

=C2=A0 =C2=A0 a)=C2=A0 You need to check that= any child exist separately before accessing its properties, because trying= to access properties on a non-existing value is a fatal error.
=C2=A0 =C2=A0 b)=C2=A0 Don=E2=80=99t forget to reassign any ele= ments which you have changed to the right place in the structure or the cha= nge may not take effect. It=E2=80=99s not all that clear when it is needed = so it=E2=80=99s safer to do it always.

=C2=A0 =C2=A0 Here is a more explicit version (with more com= ments and some extras :-) of my filter for conditionally stripping the Figu= re around an Image:

=C2= =A0 =C2=A0 ```lua
=C2=A0 =C2=A0 function Figure(fig)=
=C2=A0 =C2=A0 =C2=A0 -- First check that we have ex= actly one child...
=C2=A0 =C2=A0 =C2=A0 if 1 =3D=3D = #fig.content then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 local = child =3D fig.content[1]
=C2=A0 =C2=A0 =C2=A0 =C2=A0= -- ...then check that the child is a Plain...
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 if 'Plain' =3D=3D child.tag then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- ...then check that ther= e is exactly one grandchild...
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 if 1 =3D=3D #child.content then
=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 local grandchild =3D child.content[1]
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- ...and t= hat the grandchild is an Image.
=C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 if 'Image' =3D=3D grandchild.tag then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Bingo!<= /div>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- = Now do we want it to be a figure?
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if grandchild.classes:includes('fig'= ;) then
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 grandchild.attributes.style =3D style_for_img_in_fig
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- P= ut grandchild back
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 child.content[1] =3D grandchild
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Put child b= ack
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 fig.content[1] =3D child
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 fig.attributes.style =3D style_for_f= igs
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 -- Done with figure
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return fig
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- else if a standalone image
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 grand= child.attributes.style =3D style_for_img
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 -- Don't want the fig so return = the image!
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 return granchild
=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 end
=C2=A0 =C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 =C2=A0 end
=C2=A0 =C2=A0 = =C2=A0 -- If not all the conditions hold
=C2=A0 =C2= =A0 =C2=A0 return nil
=C2=A0 =C2=A0 end
=C2=A0 =C2=A0 ```

=C2=A0 =C2=A0 (Note: the `style_for_*` variables aren=E2=80=99t actual= ly defined in this code; they are just placeholders for some strings!)



I thought
print(pandoc.utils.stringify(el.content[1].content[1].attr.attributes))
would give me the attributes but it does not.
<= div dir=3D"auto">
`pandoc.utils.stringify` conca= tenates and returns the Str element values in its argument, which must be a= n element object. The attributes of an element don't meet any of those = two descriptions, but they are an object with custom stringification (in th= e Lua sense) so you can just say `print(element.attributes)` to inspect the= m.



Could this be a bug?

No.

=

--
You received this message because you are subscribed to the Google Groups &= quot;pandoc-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to pandoc-discuss+unsubscribe@googlegroups.= com.
To view this discussion on the web visit https://groups.google= .com/d/msgid/pandoc-discuss/37d8c191-388e-164e-6955-9014b4f0a4a0%40meddatai= nc.com.

--
You received this message because you are subscribed to the Google Groups &= quot;pandoc-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an e= mail to pand= oc-discuss+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org.
To view this discussion on the web visit https://group= s.google.com/d/msgid/pandoc-discuss/CADAJKhBjJTZki4np%3DoSfbbcmtBjEahCU4440= tRfOh_6TMzSAYw%40mail.gmail.com.
--00000000000077056305fe2aa836--