aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sisudoc
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-09-30 14:32:03 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-09-30 22:31:56 -0400
commit36d0935c9a7521a87929d676a6b657fb033c44eb (patch)
treeacb1e27aa0a95691419e2b05f5623fbd4f1aac61 /src/sisudoc
parentunused function removed (diff)
notes: editor's notes, ~[* ]~ & ~[+ ]~, as series
The markup documents ~[* note ]~ and ~[+ note ]~ as editor's notes, each a separately numbered series, and a bare ~[ note ]~ which sisu put in the asterisk series. They are included as notes. Each series is numbered through the document, *1, *2 ... and +1, +2 ..., apart from the author's notes. (assisted by Claude-Code)
Diffstat (limited to 'src/sisudoc')
-rw-r--r--src/sisudoc/ocda/meta/metadoc_from_src_functions.d39
-rw-r--r--src/sisudoc/ocda/meta/rgx.d11
-rw-r--r--src/sisudoc/outputs/io_out/latex.d14
-rw-r--r--src/sisudoc/outputs/io_out/odt.d21
-rw-r--r--src/sisudoc/outputs/io_out/rgx.d10
-rw-r--r--src/sisudoc/outputs/io_out/text.d5
6 files changed, 84 insertions, 16 deletions
diff --git a/src/sisudoc/ocda/meta/metadoc_from_src_functions.d b/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
index c5a63cd..922f389 100644
--- a/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
+++ b/src/sisudoc/ocda/meta/metadoc_from_src_functions.d
@@ -2340,7 +2340,7 @@ template docAbstractionFunctions() {
// ↓ - object inline munge
static struct ObjInlineMarkupMunge {
string[string] obj_txt;
- int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
+ int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus, n_foot_ed_asterisk, n_foot_ed_plus;
string asterisks_, plus_;
string obj_txt_out, tail, note;
static auto rgx = RgxI();
@@ -2351,6 +2351,8 @@ template docAbstractionFunctions() {
n_foot_reg = 0;
n_foot_sp_asterisk = 0;
n_foot_sp_plus = 0;
+ n_foot_ed_asterisk = 0;
+ n_foot_ed_plus = 0;
}
static auto images()(string obj_txt_in) {
static auto mng = InlineMarkup();
@@ -2381,13 +2383,13 @@ template docAbstractionFunctions() {
bool flg_notes_reg = false;
bool flg_notes_star = false;
bool flg_notes_plus = false;
+ if (!(stage_reset_note_numbers) && reset_note_numbers) {
+ stage_reset_note_numbers = true;
+ }
obj_txt_in = obj_txt_in.replaceAll(
rgx.inline_notes_curly,
(mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
);
- if (!(stage_reset_note_numbers) && reset_note_numbers) {
- stage_reset_note_numbers = true;
- }
obj_txt_out = "";
if (obj_txt_in.match(rgx.inline_notes_al_gen)) {
string[] _tmp_txt;
@@ -2398,6 +2400,8 @@ template docAbstractionFunctions() {
n_foot_reg = 0;
n_foot_sp_asterisk = 0;
n_foot_sp_plus = 0;
+ n_foot_ed_asterisk = 0;
+ n_foot_ed_plus = 0;
}
stage_reset_note_numbers = false;
foreach(n; m) {
@@ -2439,6 +2443,33 @@ template docAbstractionFunctions() {
} else {
obj_txt_out = obj_txt_in;
}
+ /+ ↓ editor's notes: ~[* note ]~ and ~[+ note ]~, and a bare ~[ note ]~,
+ which joins the asterisk series as it did in sisu. Each series is
+ numbered through the document, apart from the author's notes:
+ *1, *2 ... and +1, +2 ...
+ .
+ Placed after the author's notes rather than before, so that the reset
+ above, made once per document at its first note, has happened by the
+ time these are counted.
+ +/
+ if (obj_txt_out.match(rgx.inline_notes_square)) {
+ if (stage_reset_note_numbers) {
+ n_foot = 0;
+ n_foot_reg = 0;
+ n_foot_sp_asterisk = 0;
+ n_foot_sp_plus = 0;
+ n_foot_ed_asterisk = 0;
+ n_foot_ed_plus = 0;
+ stage_reset_note_numbers = false;
+ }
+ obj_txt_out = replaceAll!((m) {
+ string _series = (m["series"] == "+") ? "+" : "*";
+ int _n = (_series == "+") ? ++n_foot_ed_plus : ++n_foot_ed_asterisk;
+ if (_series == "+") { flg_notes_plus = true; }
+ return mkup.en_a_o ~ _series ~ _n.to!string ~ " " ~ m["note"] ~ mkup.en_a_c;
+ })(obj_txt_out, rgx.inline_notes_square);
+ flg_notes_star = true;
+ }
ST_txtPlusHasFootnotes ret;
{
ret.obj_txt = obj_txt_out;
diff --git a/src/sisudoc/ocda/meta/rgx.d b/src/sisudoc/ocda/meta/rgx.d
index 249fd3d..22828d7 100644
--- a/src/sisudoc/ocda/meta/rgx.d
+++ b/src/sisudoc/ocda/meta/rgx.d
@@ -151,6 +151,7 @@ static template spineRgxIn() {
static inline_notes_curly = ctRegex!(`~\{\s*(.+?)\s*\}~`, "mg");
static inline_notes_curly_sp_asterisk = ctRegex!(`~\{[*]+\s+(.+?)\s*\}~`, "m");
static inline_notes_curly_sp_plus = ctRegex!(`~\{[+]+\s+(.+?)\s*\}~`, "m");
+ static inline_notes_square = ctRegex!(`~\[\s*(?P<series>[*+]?)\s*(?P<note>.+?)\s*\]~`, "mg"); // editor's notes, their own numbered series
static note_ref = ctRegex!(`^\S+?noteref_(?P<ref>[0-9]+)`, "mg"); // {^{73.}^}#noteref_73
static smid_inline_url_generic = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_#]`, "mg");
static smid_inline_url = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg");
@@ -236,17 +237,17 @@ static template spineRgxIn() {
+/
static trailing_backslash = ctRegex!(`\s*\\`, "mg");
/+ inline markup footnotes endnotes +/
- static inline_notes_al = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
- static inline_notes_al_special = ctRegex!(`【(?:[*+]\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented
+ static inline_notes_al = ctRegex!(`【(?:[*+]+[0-9]*\s+|\s*)(.+?)】`, "mg");
+ static inline_notes_al_special = ctRegex!(`【(?:[*+]+[0-9]*\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented
static inline_notes_al_gen = ctRegex!(`【.+?】`, "m");
static inline_notes_al_gen_text = ctRegex!(`【(?P<text>.+?)】`, "m");
- static inline_notes_al_all_note = ctRegex!(`【(?P<num>\d+|(?:[*]|[+])+)\s+(?P<note>.+?)\s*】`, "mg");
+ static inline_notes_al_all_note = ctRegex!(`【(?P<num>\d+|[*+]+[0-9]*)\s+(?P<note>.+?)\s*】`, "mg");
static inline_notes_al_regular_number_note = ctRegex!(`【(?P<num>\d+)\s+(?P<note>.+?)\s*】`, "mg");
- static inline_notes_al_special_char_note = ctRegex!(`【(?P<char>(?:[*]|[+])+)\s+(?P<note>.+?)】`, "mg");
+ static inline_notes_al_special_char_note = ctRegex!(`【(?P<char>[*+]+[0-9]*)\s+(?P<note>.+?)】`, "mg");
static inline_al_delimiter_open_regular = ctRegex!(`【\s`, "m");
static inline_al_delimiter_open_symbol_star = ctRegex!(`【[*]\s`, "m");
static inline_al_delimiter_open_symbol_plus = ctRegex!(`【[+]\s`, "m");
- static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|.+))`, "mg");
+ static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*[0-9]*\s+.+?】|.+))`, "mg");
static endnote_section_note = ctRegex!(`┥\s*⑆\^┨(?P<notenumber>\d+)\.┣\^┝┤(?P<link>¤?.+?)├.+`, "mg");
/+ inline markup links +/
static inline_image = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.*?├)`, "mg");
diff --git a/src/sisudoc/outputs/io_out/latex.d b/src/sisudoc/outputs/io_out/latex.d
index 8e7b37c..1562fae 100644
--- a/src/sisudoc/outputs/io_out/latex.d
+++ b/src/sisudoc/outputs/io_out/latex.d
@@ -494,6 +494,20 @@ template outputLaTeX() {
"$2".strip
).strip
);
+ /+ ↓ a note of a special series (*, *1, +1 ...). \footnote[n] takes a
+ number, so the mark is set as \thefootnote for this one note,
+ and the counter put back, so that the numbered series does not
+ move.
+ +/
+ _txt = replaceAll!((m) {
+ import std.array : replace;
+ string _mark = m["char"];
+ string _name = _mark.replace("*", "a").replace("+", "p");
+ return "\\hypertarget{noteref_" ~ _name ~ "}{}"
+ ~ "{\\renewcommand{\\thefootnote}{" ~ _mark ~ "}"
+ ~ "\\footnote{\\label{note_" ~ _name ~ "}" ~ m["note"].strip ~ "}"
+ ~ "\\addtocounter{footnote}{-1}}";
+ })(_txt, rgx.inline_notes_al_special_char_note);
}
return _txt;
}
diff --git a/src/sisudoc/outputs/io_out/odt.d b/src/sisudoc/outputs/io_out/odt.d
index 40d760d..d8f6c2f 100644
--- a/src/sisudoc/outputs/io_out/odt.d
+++ b/src/sisudoc/outputs/io_out/odt.d
@@ -107,6 +107,8 @@ template formatODT() {
return _on;
}
string _footnotes()(string _txt) {
+ import std.array : replace;
+ import std.regex : replaceAll;
static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
_txt = _txt.replaceAll(
@@ -124,6 +126,25 @@ template formatODT() {
"$1", "$1", "$2",
)
);
+ /+ ↓ a note of a special series (*, *1, +1 ...): the same footnote, carrying
+ its mark as the citation's label, since odf numbers a note itself unless
+ instructed otherwise. The id takes the mark spelled in letters, "*" and
+ "+" having no place in one.
+ +/
+ _txt = replaceAll!((m) {
+ string _mark = m["char"];
+ string _id = _mark.replace("*", "a").replace("+", "p");
+ return format(q"┃<text:note text:id="ftn_%s" text:note-class="footnote">
+ <text:note-citation text:label="%s">%s</text:note-citation>
+ <text:note-body>
+ <text:p text:style-name="Footnote">
+ %s
+ </text:p>
+ </text:note-body>
+ </text:note>┃",
+ _id, _mark, _mark, m["note"].strip,
+ );
+ })(_txt, rgx.inline_notes_al_special_char_note);
return _txt;
}
string _bullet(O)(const O obj) {
diff --git a/src/sisudoc/outputs/io_out/rgx.d b/src/sisudoc/outputs/io_out/rgx.d
index 60e169b..d2e842c 100644
--- a/src/sisudoc/outputs/io_out/rgx.d
+++ b/src/sisudoc/outputs/io_out/rgx.d
@@ -93,17 +93,17 @@ static template spineRgxOut() {
/+ quotation marks +/
static quotes_open_and_close = ctRegex!(`[“”]`, "mg");
/+ inline markup footnotes endnotes +/
- static inline_notes_al = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
- static inline_notes_al_special = ctRegex!(`【(?:[*+]\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented
+ static inline_notes_al = ctRegex!(`【(?:[*+]+[0-9]*\s+|\s*)(.+?)】`, "mg");
+ static inline_notes_al_special = ctRegex!(`【(?:[*+]+[0-9]*\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented
static inline_notes_al_gen = ctRegex!(`【.+?】`, "m");
static inline_notes_al_gen_text = ctRegex!(`【(?P<text>.+?)】`, "m");
- static inline_notes_al_all_note = ctRegex!(`【(?P<num>\d+|(?:[*]|[+])+)\s+(?P<note>.+?)\s*】`, "mg");
+ static inline_notes_al_all_note = ctRegex!(`【(?P<num>\d+|[*+]+[0-9]*)\s+(?P<note>.+?)\s*】`, "mg");
static inline_notes_al_regular_number_note = ctRegex!(`【(?P<num>\d+)\s+(?P<note>.+?)\s*】`, "mg");
- static inline_notes_al_special_char_note = ctRegex!(`【(?P<char>(?:[*]|[+])+)\s+(?P<note>.+?)】`, "mg");
+ static inline_notes_al_special_char_note = ctRegex!(`【(?P<char>[*+]+[0-9]*)\s+(?P<note>.+?)】`, "mg");
static inline_al_delimiter_open_regular = ctRegex!(`【\s`, "m");
static inline_al_delimiter_open_symbol_star = ctRegex!(`【[*]\s`, "m");
static inline_al_delimiter_open_symbol_plus = ctRegex!(`【[+]\s`, "m");
- static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|.+))`, "mg");
+ static inline_text_and_note_al_ = ctRegex!(`(.+?(?:【[*+]*[0-9]*\s+.+?】|.+))`, "mg");
static endnote_section_note = ctRegex!(`┥\s*⑆\^┨(?P<notenumber>\d+)\.┣\^┝┤(?P<link>¤?.+?)├.+`, "mg");
/+ inline markup links +/
static inline_image = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>[a-zA-Z0-9._-]+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.*?├)`, "mg");
diff --git a/src/sisudoc/outputs/io_out/text.d b/src/sisudoc/outputs/io_out/text.d
index 89e85d9..43c7705 100644
--- a/src/sisudoc/outputs/io_out/text.d
+++ b/src/sisudoc/outputs/io_out/text.d
@@ -110,13 +110,14 @@ template outputText() {
string general_munge;
_ocn = (obj.metainfo.ocn == 0 || doc_matters.opt.action.ocn_off)
? "" : "「" ~ obj.metainfo.ocn.to!string ~ "」" ~ newline;
+ /+ ↓ every note, numbered (1, 2 ...) or of a special series (*, *1, +1 ...) +/
if (_txt.matchFirst(rgx.inline_notes_al_gen)) {
- foreach (m; _txt.matchAll(rgx.inline_notes_al_regular_number_note)) {
+ foreach (m; _txt.matchAll(rgx.inline_notes_al_all_note)) {
_notes ~= newlines ~ m["num"] ~ ". "
~ special_characters_and_font_face!().general(m["note"].replaceAll(rgx.inline_link, ("$1")));
}
}
- _txt = _txt.replaceAll(rgx.inline_notes_al_regular_number_note, "[$1]");
+ _txt = _txt.replaceAll(rgx.inline_notes_al_all_note, "[$1]");
_txt = (obj.metainfo.is_a == "code")
? special_characters_and_font_face!().code(_txt)
: special_characters_and_font_face!().general(_txt);