From e9cfad51cda2d7ee0eb11de34d6f7a0aa0f417e5 Mon Sep 17 00:00:00 2001 From: Bastien Dumont Date: Sat, 29 Oct 2022 18:56:13 +0200 Subject: [PATCH] ConTeXt: Revert to the strategy of inverting the label and the footnote content Users will be able to use block content in labelized footnotes again. --- README.md | 20 ++++++++++++- text-crossrefs.lua | 72 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index eb553f8..c406a8b 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,25 @@ All references are wrapped in a macro named `\tcrfenum`. It has two optional arg It is up to you to define `\tcrfenum` in your preamble. If your target format is LaTeX, it should be possible to define it as a wrapper for the `\zcref` macro provided by [the zref-clever package](https://ctan.org/pkg/zref-clever). Alternatively, you can use [my implementation](TODO), which supports ConTeXt, LaTeX and other formats. Here are some hints about the implementation: * [The `\tcrfenum` macro is supposed to output the numbers along with the prefixes and delimiters (e.g. “p. ” and “–”)]{#prefixes-tex}; - * In ConTeXt, there is no way to retrieve the note number from a `\reference` or a `\pagereference` contained in the note as is customary in LaTeX. to work around this, footnotes are labelled automatically with the first identifier attached to a span in the note suffixed with `_note`. + * In ConTeXt, there is no way to retrieve the note number from a `\reference` or a `\pagereference` contained in the note as is customary in LaTeX. to work around this, footnotes are labelled automatically with the first identifier attached to a span in the note prefixed with `note:`. Contrary to the ConTeXt syntax, this label is placed _after_ the footnote content, which implies redefining the `\footnote` macro. If your template includes the `header-includes` metadata variable like in the default template, this redefinition will happen automatically. Otherwise, you can copy-paste the following code in your preamble: + +``` {=tex} +\catcode`\@=11 +\let\origfootnote\footnote +\def\footnote#1#2{ + \def\tcrf@secondArg{#2}% + \ifx\tcrf@secondArg\tcrf@bracket + \def\tcrf@todo{\tcrf@footnote@withlabel{#1}#2} % + \else + \def\tcrf@todo{\origfootnote{#1}#2}% + \fi + \tcrf@todo +} +\def\tcrf@bracket{[} +\def\tcrf@footnote@withlabel#1[#2]{\origfootnote[#2]{#1}} +\catcode`\@=13 + +``` ## Usage diff --git a/text-crossrefs.lua b/text-crossrefs.lua index 981d129..268b0b5 100644 --- a/text-crossrefs.lua +++ b/text-crossrefs.lua @@ -5,6 +5,46 @@ local REF_TYPE_ATTR = 'reftype' local PREFIXED_ATTR = 'prefixref' local RAW_ATTRIBUTE +-- ConTeXt-specific tweak in order to add the label to the footnote +--[[ + Placing the label in square brackets immediatly after \footnote + in the regular way would require unpacking the content + of the Note and wrapping them with the RawInlines + '\footnote[note:' .. label .. ']{' and '}'. + However, Notes have the strange property of being Inlines + that contain Blocks, so this would result in Blocks being + brought into the content of the object that contains the Note, + which would be invalid. + That's why we place the label at the end of the \footnote + and redefine the macro so that it takes it into account. +]]-- + +local function tweak_footnote_if_ConTeXt(metadata) + if RAW_ATTRIBUTE == 'context' then + local footnote_redefinition = [[ +\catcode`\@=11 +\let\origfootnote\footnote +\def\footnote#1#2{ + \def\tcrf@secondArg{#2}% + \def\tcrf@bracket{[}% + \ifx\tcrf@secondArg\tcrf@bracket + \def\tcrf@todo{\tcrf@footnote@withlabel{#1}#2} % + \else + \def\tcrf@todo{\origfootnote{#1}#2}% + \fi + \tcrf@todo +} +\def\tcrf@footnote@withlabel#1[#2]{\origfootnote[#2]{#1}} +\catcode`\@=13 + ]] + if not metadata['header-includes'] then + metadata['header-includes'] = pandoc.MetaBlocks(pandoc.RawBlock('context', '')) + end + metadata['header-includes']:insert(pandoc.RawBlock('context', footnote_redefinition)) + end + return metadata +end + -- Configuration local function define_raw_attribute() @@ -178,30 +218,31 @@ local collect_note_labels = { } local function make_notelabel(pos) + -- About the strategy followed with ConTeXt, + -- see above tweak_footnote_if_ConTeXt. local raw_code = '' if pos == 'begin' then - raw_code = string.gsub( - '', - '{{label}}', current_note_labels[1]) + if RAW_ATTRIBUTE == 'openxml' then + raw_code = string.gsub( + '', + '{{label}}', current_note_labels[1]) + end elseif pos == 'end' then - raw_code = string.gsub('', - '{{label}}', current_note_labels[1]) + if RAW_ATTRIBUTE == 'openxml' then + raw_code = string.gsub('', + '{{label}}', current_note_labels[1]) + elseif RAW_ATTRIBUTE == 'context' then + raw_code = '[note:' .. current_note_labels[1] .. ']' + end end return pandoc.RawInline(RAW_ATTRIBUTE, raw_code) end local function labelize_note(note) local labelized_note - if RAW_ATTRIBUTE == 'openxml' then - local label_begin = make_notelabel('begin') - local label_end = make_notelabel('end') - labelized_note = { label_begin, note, label_end } - elseif RAW_ATTRIBUTE == 'context' then - labelized_note = pandoc.utils.blocks_to_inlines(note.content) - labelized_note:insert(1, pandoc.RawInline('context', '\\footnote[note:' .. current_note_labels[1] .. ']{')) - labelized_note:insert(pandoc.RawInline('context', '}')) - end - return labelized_note + local label_begin = make_notelabel('begin') + local label_end = make_notelabel('end') + return { label_begin, note, label_end } end local function map_text_to_note_labels(current_note_labels) @@ -545,6 +586,7 @@ end return { { Meta = configure }, + { Meta = tweak_footnote_if_ConTeXt }, { Note = set_notelabels }, { Note = map_spans_to_notelabels }, { Span = labelize_span },