forked from mirrors/org-mode
ox: Support unnumbered headlines via property
* ox.el (org-export--collect-headline-numbering): Ignore unnumbered headline. (org-export-get-headline-id, org-export--collect-unnumbered-headline-id): New functions. (org-export-numbered-headline-p): Further tests for unnumbered headline. * ox-odt.el (org-odt-headline, org-odt-link, org-odt-link--infer-description) ox-md.el (org-md-headline, org-md-link), ox-latex.el (org-latex-headline, org.latex-link), ox-html.el (org-html-headline, org-html-link), ox-ascii.el (org-ascii-link): Support unnumbered headlines. * test-ox.el (test-org-export/org-export-get-headline-id): New test. * OrgOdtStyles.xml: Add styles for unnumbered headings.
This commit is contained in:
parent
4412fed850
commit
464cd965cb
|
@ -109,33 +109,52 @@
|
|||
</style:style>
|
||||
<style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
|
||||
<style:text-properties fo:font-size="115%" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
|
||||
<style:style style:name="Heading_20_1_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_1" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_2_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_2" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
|
||||
<style:text-properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_3_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_3" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
|
||||
<style:text-properties fo:font-size="85%" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="85%" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-style-complex="italic" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_4_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_4" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text">
|
||||
<style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_5_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_5" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_6" style:display-name="Heading 6" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="6" style:class="text">
|
||||
<style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_6_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_6" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_7" style:display-name="Heading 7" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="7" style:class="text">
|
||||
<style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_7_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_7" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_8" style:display-name="Heading 8" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="8" style:class="text">
|
||||
<style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_8_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_8" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_9" style:display-name="Heading 9" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="9" style:class="text">
|
||||
<style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_9_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_9" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_10" style:display-name="Heading 10" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="10" style:class="text">
|
||||
<style:text-properties fo:font-size="75%" fo:font-weight="bold" style:font-size-asian="75%" style:font-weight-asian="bold" style:font-size-complex="75%" style:font-weight-complex="bold"/>
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_10_unnumbered" style:family="paragraph" style:parent-style-name="Heading_20_10" style:list-style-name="">
|
||||
</style:style>
|
||||
<style:style style:name="Heading_20_1.title" style:display-name="Heading 1.title" style:family="paragraph" style:parent-style-name="Heading_20_1">
|
||||
<style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/>
|
||||
|
|
|
@ -15340,7 +15340,7 @@ but in some other way.")
|
|||
"LOCATION" "LOGGING" "COLUMNS" "VISIBILITY"
|
||||
"TABLE_EXPORT_FORMAT" "TABLE_EXPORT_FILE"
|
||||
"EXPORT_OPTIONS" "EXPORT_TEXT" "EXPORT_FILE_NAME"
|
||||
"EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE"
|
||||
"EXPORT_TITLE" "EXPORT_AUTHOR" "EXPORT_DATE" "UNNUMBERED"
|
||||
"ORDERED" "NOBLOCKING" "COOKIE_DATA" "LOG_INTO_DRAWER" "REPEAT_TO_STATE"
|
||||
"CLOCK_MODELINE_TOTAL" "STYLE" "HTML_CONTAINER_CLASS")
|
||||
"Some properties that are used by Org-mode for various purposes.
|
||||
|
|
|
@ -1530,9 +1530,13 @@ INFO is a plist holding contextual information."
|
|||
(let ((number
|
||||
(org-export-get-ordinal
|
||||
destination info nil 'org-ascii--has-caption-p)))
|
||||
(when number
|
||||
(if number
|
||||
(if (atom number) (number-to-string number)
|
||||
(mapconcat 'number-to-string number "."))))))))
|
||||
(mapconcat #'number-to-string number "."))
|
||||
;; Unnumbered headline.
|
||||
(when (eq 'headline (org-element-type destination))
|
||||
(format "[%s]" (org-export-data
|
||||
(org-element-property :title destination) info)))))))))
|
||||
(t
|
||||
(if (not (org-string-nw-p desc)) (format "[%s]" raw-link)
|
||||
(concat (format "[%s]" desc)
|
||||
|
|
|
@ -2096,8 +2096,7 @@ INFO is a plist used as a communication channel."
|
|||
;; Label.
|
||||
(org-export-solidify-link-text
|
||||
(or (org-element-property :CUSTOM_ID headline)
|
||||
(concat "sec-"
|
||||
(mapconcat #'number-to-string headline-number "-"))))
|
||||
(org-export-get-headline-id headline info)))
|
||||
;; Body.
|
||||
(concat
|
||||
(and (not (org-export-low-level-p headline info))
|
||||
|
@ -2321,7 +2320,8 @@ holding contextual information."
|
|||
(unless (org-element-property :footnote-section-p headline)
|
||||
(let* ((numberedp (org-export-numbered-headline-p headline info))
|
||||
(numbers (org-export-get-headline-number headline info))
|
||||
(section-number (mapconcat #'number-to-string numbers "-"))
|
||||
(section-number (and numbers
|
||||
(mapconcat #'number-to-string numbers "-")))
|
||||
(level (+ (org-export-get-relative-level headline info)
|
||||
(1- (plist-get info :html-toplevel-hlevel))))
|
||||
(todo (and (plist-get info :with-todo-keywords)
|
||||
|
@ -2338,7 +2338,7 @@ holding contextual information."
|
|||
(contents (or contents ""))
|
||||
(ids (delq nil
|
||||
(list (org-element-property :CUSTOM_ID headline)
|
||||
(concat "sec-" section-number)
|
||||
(org-export-get-headline-id headline info)
|
||||
(org-element-property :ID headline))))
|
||||
(preferred-id (car ids))
|
||||
(extra-ids (mapconcat
|
||||
|
@ -2369,7 +2369,7 @@ holding contextual information."
|
|||
(org-html--container headline info)
|
||||
(format "outline-container-%s"
|
||||
(or (org-element-property :CUSTOM_ID headline)
|
||||
(concat "sec-" section-number)))
|
||||
(org-export-get-headline-id headline info)))
|
||||
(concat (format "outline-%d" level)
|
||||
(and extra-class " ")
|
||||
extra-class)
|
||||
|
@ -2808,20 +2808,11 @@ INFO is a plist holding contextual information. See
|
|||
;; Link points to a headline.
|
||||
(headline
|
||||
(let ((href
|
||||
;; What href to use?
|
||||
(cond
|
||||
;; Case 1: Headline is linked via it's CUSTOM_ID
|
||||
;; property. Use CUSTOM_ID.
|
||||
((string= type "custom-id")
|
||||
(org-element-property :CUSTOM_ID destination))
|
||||
;; Case 2: Headline is linked via it's ID property
|
||||
;; or through other means. Use the default href.
|
||||
((member type '("id" "fuzzy"))
|
||||
(format "sec-%s"
|
||||
(mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
destination info) "-")))
|
||||
(t (error "Shouldn't reach here"))))
|
||||
;; Headline linked via CUSTOM_ID.
|
||||
(or (and (string= type "custom-id")
|
||||
(org-element-property :CUSTOM_ID destination))
|
||||
(org-export-get-headline-id destination info)
|
||||
(t (error "Shouldn't reach here"))))
|
||||
;; What description to use?
|
||||
(desc
|
||||
;; Case 1: Headline is numbered and LINK has no
|
||||
|
@ -3073,13 +3064,16 @@ holding contextual information."
|
|||
(let* ((class-num (+ (org-export-get-relative-level parent info)
|
||||
(1- (plist-get info :html-toplevel-hlevel))))
|
||||
(section-number
|
||||
(mapconcat
|
||||
'number-to-string
|
||||
(org-export-get-headline-number parent info) "-")))
|
||||
(and (org-export-numbered-headline-p parent info)
|
||||
(mapconcat
|
||||
#'number-to-string
|
||||
(org-export-get-headline-number parent info) "-"))))
|
||||
;; Build return value.
|
||||
(format "<div class=\"outline-text-%d\" id=\"text-%s\">\n%s</div>"
|
||||
class-num
|
||||
(or (org-element-property :CUSTOM_ID parent) section-number)
|
||||
(or (org-element-property :CUSTOM_ID parent)
|
||||
section-number
|
||||
(org-export-get-headline-id parent info))
|
||||
contents)))))
|
||||
|
||||
;;;; Radio Target
|
||||
|
|
|
@ -1477,15 +1477,10 @@ holding contextual information."
|
|||
todo todo-type priority text tags info))
|
||||
;; Associate \label to the headline for internal links.
|
||||
(headline-label
|
||||
(let ((custom-label
|
||||
(and (plist-get info :latex-custom-id-labels)
|
||||
(org-element-property :CUSTOM_ID headline))))
|
||||
(if custom-label (format "\\label{%s}\n" custom-label)
|
||||
(format "\\label{sec-%s}\n"
|
||||
(mapconcat
|
||||
#'number-to-string
|
||||
(org-export-get-headline-number headline info)
|
||||
"-")))))
|
||||
(format "\\label{%s}\n"
|
||||
(or (and (plist-get info :latex-custom-id-labels)
|
||||
(org-element-property :CUSTOM_ID headline))
|
||||
(org-export-get-headline-id headline info))))
|
||||
(pre-blanks
|
||||
(make-string (org-element-property :pre-blank headline) 10)))
|
||||
(if (or (not section-fmt) (org-export-low-level-p headline info))
|
||||
|
@ -1975,14 +1970,8 @@ INFO is a plist holding contextual information. See
|
|||
(let* ((custom-label
|
||||
(and (plist-get info :latex-custom-id-labels)
|
||||
(org-element-property :CUSTOM_ID destination)))
|
||||
(label
|
||||
(or
|
||||
custom-label
|
||||
(format "sec-%s"
|
||||
(mapconcat
|
||||
#'number-to-string
|
||||
(org-export-get-headline-number destination info)
|
||||
"-")))))
|
||||
(label (or custom-label
|
||||
(org-export-get-headline-id destination info))))
|
||||
(if (and (not desc)
|
||||
(org-export-numbered-headline-p destination info))
|
||||
(format "\\ref{%s}" label)
|
||||
|
|
|
@ -204,10 +204,7 @@ a communication channel."
|
|||
(when (plist-get info :with-toc)
|
||||
(org-html--anchor
|
||||
(or (org-element-property :CUSTOM_ID headline)
|
||||
(concat "sec-"
|
||||
(mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
headline info) "-")))
|
||||
(org-export-get-headline-id headline info))
|
||||
nil nil info)))
|
||||
;; Headline text without tags.
|
||||
(heading (concat todo priority title))
|
||||
|
@ -330,10 +327,13 @@ a communication channel."
|
|||
(and contents (concat contents " "))
|
||||
(format "(%s)"
|
||||
(format (org-export-translate "See section %s" :html info)
|
||||
(mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
destination info)
|
||||
".")))))))
|
||||
(if (org-export-numbered-headline-p destination info)
|
||||
(mapconcat #'number-to-string
|
||||
(org-export-get-headline-number
|
||||
destination info)
|
||||
".")
|
||||
(org-export-data
|
||||
(org-element-property :title destination) info))))))))
|
||||
((org-export-inline-image-p link org-html-inline-image-rules)
|
||||
(let ((path (let ((raw-path (org-element-property :path link)))
|
||||
(if (not (file-name-absolute-p raw-path)) raw-path
|
||||
|
@ -354,9 +354,13 @@ a communication channel."
|
|||
(if (org-string-nw-p contents) contents
|
||||
(when destination
|
||||
(let ((number (org-export-get-ordinal destination info)))
|
||||
(when number
|
||||
(if number
|
||||
(if (atom number) (number-to-string number)
|
||||
(mapconcat 'number-to-string number "."))))))))
|
||||
(mapconcat #'number-to-string number "."))
|
||||
;; Unnumbered headline.
|
||||
(and (eq 'headline (org-element-type destination))
|
||||
;; BUG: shouldn't headlines have a form like [ref](name) in md?
|
||||
(org-export-data (org-element-property :title headline) info))))))))
|
||||
;; Link type is handled by a special function.
|
||||
((let ((protocol (nth 2 (assoc type org-link-protocols))))
|
||||
(and (functionp protocol)
|
||||
|
|
|
@ -1122,7 +1122,7 @@ See `org-odt--build-date-styles' for implementation details."
|
|||
(setq text
|
||||
(concat
|
||||
;; Section number.
|
||||
(when section-number (concat section-number ". "))
|
||||
(and section-number (concat section-number ". "))
|
||||
;; Todo.
|
||||
(when todo
|
||||
(let ((style (if (member todo org-done-keywords)
|
||||
|
@ -1789,8 +1789,7 @@ INFO is a plist holding contextual information."
|
|||
(org-element-property :title headline) backend info))
|
||||
(tags (and (plist-get info :with-tags)
|
||||
(org-export-get-tags headline info)))
|
||||
(headline-label (concat "sec-" (mapconcat 'number-to-string
|
||||
headline-number "-")))
|
||||
(headline-label (org-export-get-headline-id headline info))
|
||||
(format-function
|
||||
(if (functionp format-function) format-function
|
||||
(function*
|
||||
|
@ -1815,10 +1814,9 @@ holding contextual information."
|
|||
(full-text (org-odt-format-headline--wrap headline nil info))
|
||||
;; Get level relative to current parsed data.
|
||||
(level (org-export-get-relative-level headline info))
|
||||
(numbered (org-export-numbered-headline-p headline info))
|
||||
;; Get canonical label for the headline.
|
||||
(id (concat "sec-" (mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
headline info) "-")))
|
||||
(id (org-export-get-headline-id headline info))
|
||||
;; Get user-specified labels for the headline.
|
||||
(extra-ids (list (org-element-property :CUSTOM_ID headline)
|
||||
(org-element-property :ID headline)))
|
||||
|
@ -1842,8 +1840,7 @@ holding contextual information."
|
|||
(and (org-export-first-sibling-p headline info)
|
||||
(format "\n<text:list text:style-name=\"%s\" %s>"
|
||||
;; Choose style based on list type.
|
||||
(if (org-export-numbered-headline-p headline info)
|
||||
"OrgNumberedList" "OrgBulletedList")
|
||||
(if numbered "OrgNumberedList" "OrgBulletedList")
|
||||
;; If top-level list, re-start numbering. Otherwise,
|
||||
;; continue numbering.
|
||||
(format "text:continue-numbering=\"%s\""
|
||||
|
@ -1870,9 +1867,11 @@ holding contextual information."
|
|||
(t
|
||||
(concat
|
||||
(format
|
||||
"\n<text:h text:style-name=\"%s\" text:outline-level=\"%s\">%s</text:h>"
|
||||
(format "Heading_20_%s" level)
|
||||
"\n<text:h text:style-name=\"%s\" text:outline-level=\"%s\" text:is-list-header=\"%s\">%s</text:h>"
|
||||
(format "Heading_20_%s%s"
|
||||
level (if numbered "" "_unnumbered"))
|
||||
level
|
||||
(if numbered "false" "true")
|
||||
(concat extra-targets anchored-title))
|
||||
contents))))))
|
||||
|
||||
|
@ -2643,10 +2642,7 @@ Return nil, otherwise."
|
|||
(let* ((genealogy (org-export-get-genealogy destination))
|
||||
(data (reverse genealogy))
|
||||
(label (case (org-element-type destination)
|
||||
(headline
|
||||
(format "sec-%s" (mapconcat 'number-to-string
|
||||
(org-export-get-headline-number
|
||||
destination info) "-")))
|
||||
(headline (org-export-get-headline-id destination info))
|
||||
(target
|
||||
(org-element-property :value destination))
|
||||
(t (error "FIXME: Resolve %S" destination)))))
|
||||
|
@ -2692,11 +2688,15 @@ Return nil, otherwise."
|
|||
item-numbers "")))))
|
||||
;; Case 2: Locate a regular and numbered headline in the
|
||||
;; hierarchy. Display its section number.
|
||||
(let ((headline (loop for el in (cons destination genealogy)
|
||||
when (and (eq (org-element-type el) 'headline)
|
||||
(not (org-export-low-level-p el info))
|
||||
(org-export-numbered-headline-p el info))
|
||||
return el)))
|
||||
(let ((headline
|
||||
(and
|
||||
;; Test if destination is a numbered headline.
|
||||
(org-export-numbered-headline-p destination info)
|
||||
(loop for el in (cons destination genealogy)
|
||||
when (and (eq (org-element-type el) 'headline)
|
||||
(not (org-export-low-level-p el info))
|
||||
(org-export-numbered-headline-p el info))
|
||||
return el))))
|
||||
;; We found one.
|
||||
(when headline
|
||||
(format "<text:bookmark-ref text:reference-format=\"chapter\" text:ref-name=\"OrgXref.%s\">%s</text:bookmark-ref>"
|
||||
|
@ -2776,11 +2776,9 @@ INFO is a plist holding contextual information. See
|
|||
;; If there's a description, create a hyperlink.
|
||||
;; Otherwise, try to provide a meaningful description.
|
||||
(if (not desc) (org-odt-link--infer-description destination info)
|
||||
(let* ((headline-no
|
||||
(org-export-get-headline-number destination info))
|
||||
(label
|
||||
(format "sec-%s"
|
||||
(mapconcat 'number-to-string headline-no "-"))))
|
||||
(let ((label (or (and (string= type "custom-id")
|
||||
(org-element-property :CUSTOM_ID destination))
|
||||
(org-export-get-headline-id destination info))))
|
||||
(format
|
||||
"<text:a xlink:type=\"simple\" xlink:href=\"#%s\">%s</text:a>"
|
||||
label desc))))
|
||||
|
|
51
lisp/ox.el
51
lisp/ox.el
|
@ -1974,6 +1974,7 @@ Return updated plist."
|
|||
;; properties.
|
||||
(nconc
|
||||
`(:headline-numbering ,(org-export--collect-headline-numbering data info)
|
||||
:unnumbered-headline-id ,(org-export--collect-unnumbered-headline-id data info)
|
||||
:exported-data ,(make-hash-table :test 'eq :size 4001))
|
||||
info))
|
||||
|
||||
|
@ -1996,7 +1997,7 @@ OPTIONS is a plist holding export options."
|
|||
(if (= min-level 10000) 1 min-level))))
|
||||
|
||||
(defun org-export--collect-headline-numbering (data options)
|
||||
"Return numbering of all exportable headlines in a parse tree.
|
||||
"Return numbering of all exportable, numbered headlines in a parse tree.
|
||||
|
||||
DATA is the parse tree. OPTIONS is the plist holding export
|
||||
options.
|
||||
|
@ -2007,7 +2008,8 @@ for a footnotes section."
|
|||
(let ((numbering (make-vector org-export-max-depth 0)))
|
||||
(org-element-map data 'headline
|
||||
(lambda (headline)
|
||||
(unless (org-element-property :footnote-section-p headline)
|
||||
(when (and (org-export-numbered-headline-p headline options)
|
||||
(not (org-element-property :footnote-section-p headline)))
|
||||
(let ((relative-level
|
||||
(1- (org-export-get-relative-level headline options))))
|
||||
(cons
|
||||
|
@ -2019,6 +2021,17 @@ for a footnotes section."
|
|||
when (> idx relative-level) do (aset numbering idx 0))))))
|
||||
options)))
|
||||
|
||||
(defun org-export--collect-unnumbered-headline-id (data options)
|
||||
"Return numbering of all exportable, unnumbered headlines.
|
||||
DATA is the parse tree. OPTIONS is the plist holding export
|
||||
options. Unnumbered headlines are numbered as a function of
|
||||
occurrence."
|
||||
(let ((num 0))
|
||||
(org-element-map data 'headline
|
||||
(lambda (headline)
|
||||
(unless (org-export-numbered-headline-p headline options)
|
||||
(list headline (incf num)))))))
|
||||
|
||||
(defun org-export--populate-ignore-list (data options)
|
||||
"Return list of elements and objects to ignore during export.
|
||||
DATA is the parse tree to traverse. OPTIONS is the plist holding
|
||||
|
@ -3873,7 +3886,12 @@ INFO is the plist used as a communication channel."
|
|||
;;
|
||||
;; `org-export-get-headline-number' returns the section number of an
|
||||
;; headline, while `org-export-number-to-roman' allows to convert it
|
||||
;; to roman numbers.
|
||||
;; to roman numbers. With an optional argument,
|
||||
;; `org-export-get-headline-number' returns a number to unnumbered
|
||||
;; headlines (used for internal id).
|
||||
;;
|
||||
;; `org-export-get-headline-id' returns the unique internal id of a
|
||||
;; headline.
|
||||
;;
|
||||
;; `org-export-low-level-p', `org-export-first-sibling-p' and
|
||||
;; `org-export-last-sibling-p' are three useful predicates when it
|
||||
|
@ -3908,17 +3926,32 @@ and the last level being considered as high enough, or nil."
|
|||
(let ((level (org-export-get-relative-level headline info)))
|
||||
(and (> level limit) (- level limit))))))
|
||||
|
||||
(defun org-export-get-headline-number (headline info)
|
||||
"Return HEADLINE numbering as a list of numbers.
|
||||
(defun org-export-get-headline-id (headline info)
|
||||
"Return a unique ID for HEADLINE.
|
||||
INFO is a plist holding contextual information."
|
||||
(cdr (assoc headline (plist-get info :headline-numbering))))
|
||||
(let ((numbered (org-export-numbered-headline-p headline info)))
|
||||
(concat
|
||||
(if numbered "sec-" "unnumbered-")
|
||||
(mapconcat #'number-to-string
|
||||
(if numbered
|
||||
(org-export-get-headline-number headline info)
|
||||
(cdr (assq headline (plist-get info :unnumbered-headline-id)))) "-"))))
|
||||
|
||||
(defun org-export-get-headline-number (headline info)
|
||||
"Return numbered HEADLINE numbering as a list of numbers.
|
||||
INFO is a plist holding contextual information."
|
||||
(and (org-export-numbered-headline-p headline info)
|
||||
(cdr (assq headline (plist-get info :headline-numbering)))))
|
||||
|
||||
(defun org-export-numbered-headline-p (headline info)
|
||||
"Return a non-nil value if HEADLINE element should be numbered.
|
||||
INFO is a plist used as a communication channel."
|
||||
(let ((sec-num (plist-get info :section-numbers))
|
||||
(level (org-export-get-relative-level headline info)))
|
||||
(if (wholenump sec-num) (<= level sec-num) sec-num)))
|
||||
(unless (org-some
|
||||
(lambda (head) (org-not-nil (org-element-property :UNNUMBERED head)))
|
||||
(cons headline (org-export-get-genealogy headline)))
|
||||
(let ((sec-num (plist-get info :section-numbers))
|
||||
(level (org-export-get-relative-level headline info)))
|
||||
(if (wholenump sec-num) (<= level sec-num) sec-num))))
|
||||
|
||||
(defun org-export-number-to-roman (n)
|
||||
"Convert integer N into a roman numeral."
|
||||
|
|
|
@ -1633,6 +1633,68 @@ Paragraph[fn:1]"
|
|||
(lambda (h) (org-export-numbered-headline-p h info))
|
||||
(plist-put info :section-numbers t)))))
|
||||
|
||||
(ert-deftest test-org-export/org-export-get-headline-id ()
|
||||
"Test `org-export-get-headline-id' specifications."
|
||||
;; Numbered headlines have IDs akin to "sec-N".
|
||||
(should
|
||||
(equal "sec-1"
|
||||
(org-test-with-parsed-data "* H"
|
||||
(org-export-get-headline-id
|
||||
(org-element-map tree 'headline #'identity info t)
|
||||
info))))
|
||||
;; The ID of numbered headlines reflect the hierarchy.
|
||||
(should
|
||||
(equal "sec-1-1"
|
||||
(org-test-with-parsed-data "* H1\n** H2"
|
||||
(org-export-get-headline-id
|
||||
(org-element-map tree 'headline
|
||||
(lambda (h)
|
||||
(and (equal "H2" (org-element-property :raw-value h)) h))
|
||||
info t)
|
||||
info))))
|
||||
;; Unnumbered headlines have IDs akin to "unnumbered-N".
|
||||
(should
|
||||
(equal "unnumbered-1"
|
||||
(org-test-with-parsed-data
|
||||
"* H\n:PROPERTIES:\n:UNNUMBERED: t\n:END:"
|
||||
(org-export-get-headline-id
|
||||
(org-element-map tree 'headline #'identity info t)
|
||||
info))))
|
||||
;; The ID of Unnumbered headlines do not reflect the hierarchy.
|
||||
(should
|
||||
(equal "unnumbered-2"
|
||||
(org-test-with-parsed-data
|
||||
"* H1\n:PROPERTIES:\n:UNNUMBERED: t\n:END:\n** H2"
|
||||
(org-export-get-headline-id
|
||||
(org-element-map tree 'headline
|
||||
(lambda (h)
|
||||
(and (equal "H2" (org-element-property :raw-value h)) h))
|
||||
info t)
|
||||
info))))
|
||||
;; When #+OPTIONS: num:nil all headlines are unnumbered.
|
||||
(should
|
||||
(equal "unnumbered-1"
|
||||
(org-test-with-parsed-data "* H\n#+OPTIONS: num:nil"
|
||||
(org-export-get-headline-id
|
||||
(org-element-map tree 'headline 'identity info t)
|
||||
info))))
|
||||
;; UNNUMBERED ignores inheritance. Any non-nil value among
|
||||
;; ancestors disables numbering.
|
||||
(should
|
||||
(org-test-with-parsed-data
|
||||
"* H
|
||||
:PROPERTIES:
|
||||
:UNNUMBERED: t
|
||||
:END:
|
||||
** H2
|
||||
:PROPERTIES:
|
||||
:UNNUMBERED: nil
|
||||
:END:
|
||||
*** H3"
|
||||
(org-every
|
||||
(lambda (h) (not (org-export-numbered-headline-p h info)))
|
||||
(org-element-map tree 'headline #'identity info)))))
|
||||
|
||||
(ert-deftest test-org-export/number-to-roman ()
|
||||
"Test `org-export-number-to-roman' specifications."
|
||||
;; If number is negative, return it as a string.
|
||||
|
|
Loading…
Reference in New Issue