From mboxrd@z Thu Jan 1 00:00:00 1970 From: "D. C. Toedt" Subject: Re: Configurable prefixes for heading-tree numbering in HTML export? ($) Date: Sat, 30 Jul 2016 17:48:33 -0500 Message-ID: References: <87oa5edbmc.fsf@saiph.selenimh> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=001a113df14c0e73b30538e22de0 Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:56901) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bTd4H-0003E3-2G for emacs-orgmode@gnu.org; Sat, 30 Jul 2016 18:49:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bTd4E-00074Y-IU for emacs-orgmode@gnu.org; Sat, 30 Jul 2016 18:49:17 -0400 Received: from mail-oi0-x234.google.com ([2607:f8b0:4003:c06::234]:33326) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bTd4E-00074U-7K for emacs-orgmode@gnu.org; Sat, 30 Jul 2016 18:49:14 -0400 Received: by mail-oi0-x234.google.com with SMTP id j185so149941986oih.0 for ; Sat, 30 Jul 2016 15:49:13 -0700 (PDT) In-Reply-To: <87oa5edbmc.fsf@saiph.selenimh> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: "D. C. Toedt" , emacs-orgmode@gnu.org --001a113df14c0e73b30538e22de0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Many thanks, Nick -- an interesting approach, but it's not a good fit for what I need. Another approach would be possible if org-mode had a way of including arbitrary attribute text in HTML exports of headings. This would enable use of the CSS attr() functionality, combined with the ::before pseudo-element and counters. I've tested out the following in HTML; it seems to work for what I need: =3D=3DBEGIN HTML SNIPPET=3D=3D

Definitions

Consulting Services

Payment Terms

General Provisions

=3D=3DEND HTML SNIPPET=3D=3D Unfortunately, org-mode does not seem to be able to include the CDArticlePrefix=3D"DEFN" attribute text in headings, as opposed to in divs. I appreciate the response. Regards, D. C. D. C. Toedt III *(My last name is pronounced "Tate")* Attorney & arbitrator -- tech contracts & IP O: +1 (713) 364-6545 C: +1 (713) 516-8968 =E2=80=8B=E2=80=8B dc@toedt.com @dctoedt =E2=80=8B Skype: dctoedt =E2=80=8B www.OnContracts.com/About =E2=80=8B=E2=80=8B Unless expressly stated otherwise, this message is not intended to serve as assent to an agreement or other document, even if attached to this message. On Sat, Jul 30, 2016 at 5:06 PM, Nicolas Goaziou wrote: > Hello, > > "D. C. Toedt" writes: > > > So far as I can tell, org-mode currently allows heading numbering in on= ly > > one style (1, 1.1, 1.1.1, etc.). For HTML export, I'm interested in > having > > the heading numbering be configurable on a per-subtree basis, along > > something like the following lines for a hypothetical > consulting-agreement > > contract (indentation is for convenient reading only). This is for my > Common > > Draft contract terms and conditions projec= t > > --- I'd like to be able to arrange the trees in an arbitrary order and > have > > the top-level headings start with prefixes and heading numbers instead = of > > heading numbers alone. > > > > This can be done in a very kludgy fashion with CSS (see below), but doi= ng > > it in org-mode would be far preferable for several reasons. > > > > I'd be happy to pay an honorarium, or make a donation, of USD$100-$200 > for > > the appropriate elisp code that I could include in the relevant file(s)= . > > I'd want the elisp code to be open-sourced, and at least minimal > > documentation, so that it could be made a candidate for possible > inclusion > > in a future org-mode release. > > > > Here's an example of the desired org-mode code: > > > > > > =3D=3D=3DBEGIN=3D=3D=3D > > > > > > * Services > > > > :PROPERTIES: > > > > :CUSTOM_ID: SVC > > > > :CUSTOM_PREFIX: t > > > > :END: > > # =3D=3D=3D=3D=3D=3D=3D=3D NOTE THE :CUSTOM_PREFIX: property above =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D # > > > > > > ** Statements of Work > > > > [properties and text omitted] > > > > > > *** Written Statements of Work Required > > > > [properties and text omitted] > > # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D AN ARBITRARY NUMBER OF SUBHEADING L= EVELS BENEATH THE TOP > > LEVEL =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D # > > > > > > *** Changes Must Be in Writing > > [properties and text omitted] > > > > > > > > ** Billing Rates > > > > [properties and text omitted] > > > > > > ** IP Ownership > > > > [properties and text omitted] > > > > > > * General Provisions > > > > :PROPERTIES: > > > > :CUSTOM_ID: GP > > :CUSTOM_PREFIX: t > > > > :END: > > > > > > ** Amendments > > > > [properties and text omitted] > > > > > > ** Notices > > > > [properties and text omitted] > > > > =3D=3D=3DEND=3D=3D=3D > > > > > > I'd like for the resulting HTML export to be something like the > following: > > > > SVC Services > > > > # =3D=3D=3D=3D=3D=3D=3D=3D NOTE THAT THERE'S NO HEADING /NUMBER/ FOR TH= E TOP-LEVEL > HEADING, > > JUST THE PREFIX =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D # > > > > > > SVC-1 Statements of Work > > > > [properties and text omitted] > > > > # =3D=3D=3D=3D=3D=3D=3D=3D PREFERABLY THE SEPARATOR IN "SVC-1" COULD BE= CONFIGURED AS A > > HYPHEN, A PERIOD, A COLON, A FORWARD SLASH, ETC. =3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D # > > > > > > SVC-1.1 Written Statements of Work Required > > > > [properties and text omitted] > > > > SVC-1.2 Changes Must Be in Writing > > > > [properties and text omitted] > > > > > > SVC-2 Billing Rates > > > > [properties and text omitted] > > > > > > SVC-3 IP Ownership > > > > [properties and text omitted] > > > > > > GP General Provisions > > > > > > GP-1 Amendments > > > > [properties and text omitted] > > > > > > GP-2 Notices > > > > [properties and text omitted] > > > > Possibly not what you're asking but, you can ignore CUSTOM_PREFIX > property altogether and use a headline filter to do what you want. > > (defun my-heading-prefix-filter (heading backend info) > "Prefix every heading and sub-heading with custom ID. > Skip one level of numbering." > (when (org-export-derived-backend-p backend 'html) > (let ((internal-ref > (and (string-match "\\`.*id=3D\"outline-container-\\(.+?\\)\= "" > heading) > (match-string 1 heading))) > (id (and (string-match "\\`.*\n" > heading) > (match-string 1 heading)))) > ;; When there is no custom ID, id attribute contains the > ;; internal reference. So we check if there is a custom ID which > ;; is going to become the prefix of all headings. > (unless (equal internal-ref id) ;No custom ID > (let ((s 0)) > (while (string-match > "\\(\\)\\(?:.*? class=3D\"section-number-[0-9]+\">\\(.+?\\)\\)?" > heading s) > (setq s (+ (match-end 0) (length id) 1)) > (setq heading > (cond > ;; Unnumbered heading. > ((not (match-end 2)) > (replace-match (concat "\\1" id " ") nil nil headin= g > 1)) > ;; Top level heading. Ignore numbering. > ((string-match-p "\\`[0-9]+\\'" (match-string 2 > heading)) > (replace-match id nil nil heading 2)) > ;; Sub-headings. Skip first number. > (t > (let ((numbers > (save-match-data > (split-string (match-string 2 heading) > "\\.")))) > (replace-match > (concat id "-" (mapconcat #'identity (cdr > numbers) ".")) > nil nil heading 2)))))) > heading))))) > > (add-to-list 'org-export-filter-headline-functions > 'my-heading-prefix-filter) > > custom ID is used to prefix every heading with its value. Of course, it > means that every heading with a custom ID is expected to follow this > pattern, so you cannot toggle the feature subtree wise. Anyway that's > a starting point. > > Regards, > > -- > Nicolas Goaziou > --001a113df14c0e73b30538e22de0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Many thanks, Nick -- a= n interesting approach, but it's not a good fit for what I need.=C2=A0<= /div>

Another approach would be possible if org-mode had a way of inc= luding arbitrary attribute text in HTML exports of headings.=C2=A0 This wou= ld enable use of the CSS attr() functionality, combined with the ::before pseudo= -element and counters. =C2=A0 I've tested out the following in HTML; it= seems to work for what I need:
=3D=3DBEGIN HTML SNIPPET=3D=3D<= /div>

<style>
body =C2=A0 { counter-r= eset: section-counter; }
h2 =C2=A0 =C2=A0 =C2=A0{= counter-reset: sub-section-counter; }
h3= = =C2=A0{ counter-reset: sub-sub-section-counter; }

h2::before {
=C2=A0 =C2= =A0 counter-increment: section-counter;
=C2=A0 =C2=A0 c= ontent: attr(CDArticlePrefix) "-" counter(section-counter) "= ";
}

h3:befor= e {
=C2=A0 =C2=A0 counter-increment: sub-section-co= unter;
=C2=A0 =C2=A0 content: attr(CDArticlePrefix) &qu= ot;-" counter(section-counter)=C2=A0"." counter(sub-section-cou= nter)=C2=A0" ";
}

<= /div>
h4:before {
=C2=A0 =C2=A0 counter-increment:= sub-sub-section-counter;
=C2=A0 =C2=A0 content: attr(CDArticlePrefix) = "-" counter(section-counter)=C2=A0"." counter(sub-section-= counter)=C2=A0"." coun= ter(sub-sub-section-counter)=C2=A0" ";
}

</style>

<h2 CDArticlePre= fix=3D"DEFN">Definitions</h2> <!-- NOTE THE "CDA= rticlePrefix" ATTRIBUTE -->

<h2 CDArticlePrefix=3D= "SERV">Consulting Services</h2>

<h2 CDArticlePrefix=3D"PMT">Payment Te= rms</h2>

<h2 CDArticlePrefix=3D"GPR">General Provi= sions</h2>

=3D=3DEND HTML = SNIPPET=3D=3D

Unfortunately, org-mode does not see= m to be able to include the CDArticlePrefix=3D"DEFN" attribute te= xt in headings, as opposed to in divs.

I appreciate the respons= e.

Regards,
<= font color=3D"#000000" face=3D"arial, helvetica, sans-serif">
D. C.

<= div dir=3D"ltr">




D. C. Toedt III=C2=A0

(My last name is pronounced "Tate")
Attorney & arbitrator -- tech co= ntracts & IP
O:=C2=A0
+1 (713) 364-6545=C2=A0 =C2=A0C:=C2=A0= +1 (713) 516-8968
=E2=80=8B=E2=80=8B=C2=A0=C2=A0
dc@toe= dt.com=C2=A0 =C2=A0=C2=A0@dctoedt=C2=A0 =C2=A0
=E2=80=8B
Skype: dctoedt
=E2=80=8B
=
www.OnContracts.co= m/About=C2=A0=C2=A0
=E2=80=8B=E2=80=8B
<= /div>

<= /div>

Unless expressly stated otherwise,
this= message=C2=A0
i= s not intended=C2=A0to serve
as
assent to an agreement=C2=A0or other document,
even if=C2=A0
attached to this message.<= /div>



On Sat, Jul 30, 2016 at 5:06 PM, Nicolas Goa= ziou <mail@nicolasgoaziou.fr> wrote:
Hello,

"D. C. Toedt" <dc@toedt.com> writes:

> So far as I can tell, org-mode currently allows heading numbering in o= nly
> one style (1, 1.1, 1.1.1, etc.).=C2=A0 For HTML export, I'm intere= sted in having
> the heading numbering be configurable on a per-subtree basis, along > something like the following lines for a hypothetical consulting-agree= ment
> contract=C2=A0 (indentation is for convenient reading only).=C2=A0 Thi= s is for my Common
> Draft <http://www.CommonDraft.org> contract terms an= d conditions project
> --- I'd like to be able to arrange the tree= s in an arbitrary order and have
> the top-level headings start with prefixes and heading numbers instead= of
> heading numbers alone.
>
> This can be done in a very kludgy fashion with CSS (see below), but do= ing
> it in org-mode would be far preferable for several reasons.
>
> I'd be happy to pay an honorarium, or make a donation, of USD$100-= $200 for
> the appropriate elisp code that I could include in the relevant file(s= ).
> I'd want the elisp code to be open-sourced, and at least minimal > documentation, so that it could be made a candidate for possible inclu= sion
> in a future org-mode release.
>
> Here's an example of the desired org-mode code:
>
>
> =3D=3D=3DBEGIN=3D=3D=3D
>
>
> * Services
>
>=C2=A0 =C2=A0:PROPERTIES:
>
>=C2=A0 =C2=A0:CUSTOM_ID: SVC
>
>=C2=A0 =C2=A0:CUSTOM_PREFIX: t
>
>=C2=A0 =C2=A0:END:
> # =3D=3D=3D=3D=3D=3D=3D=3D NOTE THE :CUSTOM_PREFIX: property above =3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D #
>
>
> ** Statements of Work
>
> [properties and text omitted]
>
>
> *** Written Statements of Work Required
>
> [properties and text omitted]
> # =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D AN ARBITRARY NUMBER OF SUBHEADING = LEVELS BENEATH THE TOP
> LEVEL =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D #
>
>
> *** Changes Must Be in Writing
> [properties and text omitted]
>
>
>
> ** Billing Rates
>
> [properties and text omitted]
>
>
> ** IP Ownership
>
> [properties and text omitted]
>
>
> * General Provisions
>
>=C2=A0 =C2=A0:PROPERTIES:
>
>=C2=A0 =C2=A0:CUSTOM_ID: GP
>=C2=A0 =C2=A0:CUSTOM_PREFIX: t
>
>=C2=A0 =C2=A0:END:
>
>
> ** Amendments
>
> [properties and text omitted]
>
>
> ** Notices
>
> [properties and text omitted]
>
> =3D=3D=3DEND=3D=3D=3D
>
>
> I'd like for the resulting HTML export to be something like the fo= llowing:
>
> SVC Services
>
> # =3D=3D=3D=3D=3D=3D=3D=3D NOTE THAT THERE'S NO HEADING /NUMBER/ F= OR THE TOP-LEVEL HEADING,
> JUST THE PREFIX =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D #
>
>
> SVC-1 Statements of Work
>
> [properties and text omitted]
>
> # =3D=3D=3D=3D=3D=3D=3D=3D PREFERABLY THE SEPARATOR IN "SVC-1&quo= t; COULD BE CONFIGURED AS A
> HYPHEN, A PERIOD, A COLON, A FORWARD SLASH, ETC. =3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D #
>
>
> SVC-1.1=C2=A0 Written Statements of Work Required
>
> [properties and text omitted]
>
> SVC-1.2=C2=A0 Changes Must Be in Writing
>
> [properties and text omitted]
>
>
> SVC-2 Billing Rates
>
> [properties and text omitted]
>
>
> SVC-3 IP Ownership
>
> [properties and text omitted]
>
>
> GP General Provisions
>
>
> GP-1 Amendments
>
> [properties and text omitted]
>
>
> GP-2 Notices
>
> [properties and text omitted]
>

Possibly not what you're asking but, you can ignore CUSTOM_= PREFIX
property altogether and use a headline filter to do what you want.

=C2=A0 (defun my-heading-prefix-filter (heading backend info)
=C2=A0 =C2=A0 "Prefix every heading and sub-heading with custom ID. =C2=A0 Skip one level of numbering."
=C2=A0 =C2=A0 (when (org-export-derived-backend-p backend 'html)
=C2=A0 =C2=A0 =C2=A0 (let ((internal-ref
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(and (string-match "\\= `.*id=3D\"outline-container-\\(.+?\\)\"" heading)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (match-strin= g 1 heading)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (id (and (string-match "\\`.= *\n<h[0-9]+ id=3D\"\\(.*?\\)\">" heading)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(match-string 1 heading))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; When there is no custom ID, id attribute con= tains the
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; internal reference.=C2=A0 So we check if the= re is a custom ID which
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ;; is going to become the prefix of all heading= s.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 (unless (equal internal-ref id)=C2=A0 =C2=A0;No= custom ID
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((s 0))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (while (string-match
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "= ;\\(<h.+?>\\)\\(?:.*?<span class=3D\"section-number-[0-9]+\&q= uot;>\\(.+?\\)</span>\\)?"
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 headi= ng s)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq s (+ (match-end 0) (= length id) 1))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (setq heading
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (cond=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0;; Unnumbered heading.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0((not (match-end 2))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (replace-match (concat "\\1" id " ") nil nil headin= g 1))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0;; Top level heading.=C2=A0 Ignore numbering.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0((string-match-p "\\`[0-9]+\\'" (match-string 2 heading))<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (replace-match id nil nil heading 2))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0;; Sub-headings.=C2=A0 Skip first number.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(t
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (let ((numbers
=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(save-match-data
=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(split-string (match-string 2 heading= ) "\\."))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 (replace-match
=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(concat id "-" (mapconcat #'identity (cdr nu= mbers) "."))
=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=A0nil nil heading 2))))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 heading)))))

=C2=A0 (add-to-list 'org-export-filter-headline-functions
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0'my-heading-pref= ix-filter)

custom ID is used to prefix every heading with its value.=C2=A0 Of course, = it
means that every heading with a custom ID is expected to follow this
pattern, so you cannot toggle the feature subtree wise. Anyway that's a starting point.

Regards,

--
Nicolas Goaziou

--001a113df14c0e73b30538e22de0--