diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/doc_reform/doc_reform.d | 18 | ||||
| -rw-r--r-- | src/doc_reform/meta/metadoc_from_src.d | 9 | ||||
| -rw-r--r-- | src/doc_reform/output/hub.d | 8 | ||||
| -rw-r--r-- | src/doc_reform/output/latex.d | 1164 | ||||
| -rw-r--r-- | src/doc_reform/output/paths_output.d | 29 | ||||
| -rw-r--r-- | src/doc_reform/output/rgx.d | 12 | 
6 files changed, 1238 insertions, 2 deletions
| diff --git a/src/doc_reform/doc_reform.d b/src/doc_reform/doc_reform.d index 25ab2cc..06866c2 100755 --- a/src/doc_reform/doc_reform.d +++ b/src/doc_reform/doc_reform.d @@ -122,6 +122,7 @@ void main(string[] args) {      "html"               : false,      "html-seg"           : false,      "html-scroll"        : false, +    "latex"              : false,      "light"              : false,      "manifest"           : false,      "ocn"                : true, @@ -129,6 +130,7 @@ void main(string[] args) {      "odt"                : false,      "parallel"           : false,      "parallel-subprocesses" : false, +    "pdf"                : false,      "quiet"              : false,      "pod"                : false,      "serial"             : false, @@ -175,6 +177,7 @@ void main(string[] args) {      "html",               "--html process html output",                                               &opts["html"],      "html-seg",           "--html-seg process html output",                                           &opts["html-seg"],      "html-scroll",        "--html-seg process html output",                                           &opts["html-scroll"], +    "latex",              "--latex output for pdfs",                                                  &opts["latex"],      "light",              "--light default light theme",                                              &opts["light"],      "manifest",           "--manifest process manifest output",                                       &opts["manifest"],      "ocn",                "--ocn object cite numbers (default)",                                      &opts["ocn"], @@ -183,6 +186,7 @@ void main(string[] args) {      "parallel",           "--parallel parallelisation",                                               &opts["parallel"],      "parallel-subprocesses", "--parallel-subprocesses nested parallelisation",                        &opts["parallel-subprocesses"],      "quiet|q",            "--quiet output to terminal",                                               &opts["quiet"], +    "pdf",                "--pdf latex output for pdfs",                                              &opts["pdf"],      "pod",                "--pod doc reform pod source content bundled",                              &opts["pod"],      "serial",             "--serial serial processing",                                               &opts["serial"],      "source",             "--source markup source text content",                                      &opts["source"], @@ -218,7 +222,7 @@ void main(string[] args) {    if (helpInfo.helpWanted) {      defaultGetoptPrinter("Some information about the program.", helpInfo.options);    } -  enum outTask { pod, source, sqlite, sqlite_multi, odt, epub, html_scroll, html_seg, html_stuff } +  enum outTask { pod, source, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }    struct OptActions {      bool assertions() {        return opts["assertions"]; @@ -270,6 +274,12 @@ void main(string[] args) {          { _is = true; } else { _is = false; }        return _is;      } +    bool latex() { +      bool _is; +      if ( opts["latex"] || opts["pdf"]) +        { _is = true; } else { _is = false; } +      return _is; +    }      bool odt() {        bool _is;        if ( opts["odf"] || opts["odt"]) @@ -392,6 +402,7 @@ void main(string[] args) {          || html          || epub          || odt +        || latex          || manifest          || pod          || source @@ -430,6 +441,9 @@ void main(string[] args) {        if (odt) {          schedule ~= outTask.odt;        } +      if (latex) { +        schedule ~= outTask.latex; +      }        return schedule.sort().uniq;      }      bool abstraction() { @@ -441,6 +455,7 @@ void main(string[] args) {          || html          || epub          || odt +        || latex          || manifest          || sqlite_discrete          || sqlite_delete @@ -454,6 +469,7 @@ void main(string[] args) {          || html          || epub          || odt +        || latex          || sqlite_discrete          || sqlite_update        ) { _is = true; } else { _is = false; } diff --git a/src/doc_reform/meta/metadoc_from_src.d b/src/doc_reform/meta/metadoc_from_src.d index 4e0120f..bd8a635 100644 --- a/src/doc_reform/meta/metadoc_from_src.d +++ b/src/doc_reform/meta/metadoc_from_src.d @@ -2254,30 +2254,36 @@ template DocReformDocAbstraction() {        "scroll": ["head", "toc", "body",],        "seg":    ["head", "toc", "body",],        "sql":    ["head", "body",], +      "latex":  ["head", "toc", "body",]      ];      if (document_the["endnotes"].length > 1) {        document_section_keys_sequenced["scroll"] ~= "endnotes";        document_section_keys_sequenced["seg"]    ~= "endnotes"; +      document_section_keys_sequenced["latex"]  ~= "endnotes";      }      if (document_the["glossary"].length > 1) {        document_section_keys_sequenced["scroll"] ~= "glossary";        document_section_keys_sequenced["seg"]    ~= "glossary";        document_section_keys_sequenced["sql"]    ~= "glossary"; +      document_section_keys_sequenced["latex"]  ~= "glossary";      }      if (document_the["bibliography"].length > 1) {        document_section_keys_sequenced["scroll"] ~= "bibliography";        document_section_keys_sequenced["seg"]    ~= "bibliography";        document_section_keys_sequenced["sql"]    ~= "bibliography"; +      document_section_keys_sequenced["latex"]  ~= "bibliography";      }      if (document_the["bookindex"].length > 1) {        document_section_keys_sequenced["scroll"] ~= "bookindex";        document_section_keys_sequenced["seg"]    ~= "bookindex";        document_section_keys_sequenced["sql"]    ~= "bookindex"; +      document_section_keys_sequenced["latex"]  ~= "bookindex";      }      if (document_the["blurb"].length > 1) {        document_section_keys_sequenced["scroll"] ~= "blurb";        document_section_keys_sequenced["seg"]    ~= "blurb";        document_section_keys_sequenced["sql"]    ~= "blurb"; +      document_section_keys_sequenced["latex"]  ~= "blurb";      }      if ((opt_action.html)      || (opt_action.html_scroll) @@ -6089,6 +6095,9 @@ template docSectKeysSeq() {        string[] sql() {          return document_section_keys_sequenced["sql"];        } +      string[] latex() { +        return document_section_keys_sequenced["latex"]; +      }      }      return doc_sect_keys_seq();    } diff --git a/src/doc_reform/output/hub.d b/src/doc_reform/output/hub.d index b840811..8f16528 100644 --- a/src/doc_reform/output/hub.d +++ b/src/doc_reform/output/hub.d @@ -15,7 +15,7 @@ template outputHub() {      mixin Msg;      auto msg = Msg!()(doc_matters);      static auto rgx = Rgx(); -    enum outTask { pod, source, sqlite, sqlite_multi, odt, epub, html_scroll, html_seg, html_stuff } +    enum outTask { pod, source, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }      void Scheduled(D,I)(int sched, D doc_abstraction, I doc_matters) {        auto msg = Msg!()(doc_matters);        if (sched == outTask.pod) { @@ -48,6 +48,12 @@ template outputHub() {          outputHTML!().images_cp(doc_matters);          msg.vv("html css & images done");        } +      if (sched == outTask.latex) { +        msg.v("latex processing... (available for downstream processing & pdf output"); +        import doc_reform.output.latex; +        outputLaTeX!()(doc_abstraction, doc_matters); +        msg.vv("latex done"); +      }        if (sched == outTask.odt) {          msg.v("odf:odt processing... ");          import doc_reform.output.odt; diff --git a/src/doc_reform/output/latex.d b/src/doc_reform/output/latex.d new file mode 100644 index 0000000..586e9fb --- /dev/null +++ b/src/doc_reform/output/latex.d @@ -0,0 +1,1164 @@ +module doc_reform.output.latex; +template outputLaTeX() { +  import doc_reform.output; +  import +    std.digest.sha, +    std.file, +    std.outbuffer, +    std.uri, +    std.conv : to; +  mixin InternalMarkup; // watch +  mixin DocReformOutputRgxInit; +  auto rgx = Rgx(); +      auto paper() { +        struct PaperType { +          auto a4() { +            struct A4 { +              auto portrait() { +                struct V { +                  uint w      = 160; +                  uint h      = 228; +                  uint img_px = 450; +                } +                return V(); +              } +              auto landscape() { +                struct H { +                  uint w      = 238; +                  uint h      = 160; +                  uint img_px = 300; +                } +                return H(); +              } +            } +            return A4(); +          } +          auto a5() { +            struct A5 { +              auto portrait() { +                struct V { +                  uint w      = 112; +                  uint h      = 162; +                  uint img_px = 280; +                } +                return V(); +              } +              auto landscape() { +                struct H { +                  uint w      = 152; +                  uint h      = 100; +                  uint img_px = 190; +                } +                return H(); +              } +            } +            return A5(); +          } +          auto b4() { +            struct B4 { +              auto portrait() { +                struct V { +                  uint w      = 140; +                  uint h      = 204; +                  uint img_px = 356; +                } +                return V(); +              } +              auto landscape() { +                struct H { +                  uint w      = 200; +                  uint h      = 130; +                  uint img_px = 260; +                } +                return H(); +              } +            } +            return B4(); +          } +          auto letter() { +            struct Letter { +              auto portrait() { +                struct V { +                  uint w      = 166; +                  uint h      = 212; +                  uint img_px = 468; +                } +                return V(); +              } +              auto landscape() { +                struct H { +                  uint w      = 226; +                  uint h      = 166; +                  uint img_px = 290; +                } +                return H(); +              } +            } +            return Letter(); +          } +          auto legal() { +            struct Legal { +              auto portrait() { +                struct V { +                  uint w      = 168; +                  uint h      = 286; +                  uint img_px = 474; +                } +                return V(); +              } +              auto landscape() { +                struct H { +                  uint w      = 296; +                  uint h      = 166; +                  uint img_px = 420; +                } +                return H(); +              } +            } +            return Legal(); +          } +        } +        return PaperType(); +      } +  string sp_char_esc(O)( +    string      _txt, +    const    O  obj, +  ) { +    string _unescape_sp_char_esc()(string _txt) { +      _txt = _txt +        .replaceAll(rgx.latex_special_char_escaped, +          format(q"┃%s┃", "$1")) +        .replaceAll(rgx.latex_special_char_escaped_braced, +          format(q"┃%s┃", "$1")); +      return _txt; +    } +    string _unescape_fontface_esc()(string _txt) { +      _txt = _txt.replaceAll(rgx.latex_identify_inline_fontface, +           format(q"┃%s%s┃", "$1", "$2")); +      return _txt; +    } +    if (obj.metainfo.is_a != "code") { +      _txt = replaceAll!(m => "\\" ~ m[1])(_txt, rgx.latex_special_char_for_escape); +      _txt = replaceAll!(m => "{\\" ~ m[1] ~ "}")(_txt, rgx.latex_special_char_for_escape_and_braces); +      _txt = replaceAll!(m => _unescape_sp_char_esc(m[0]))(_txt, rgx.latex_identify_inline_link); +      _txt = replaceAll!(m => _unescape_fontface_esc(m[0]))(_txt, rgx.latex_identify_inline_fontface); +    } +    return _txt; +  } +  string sp_char_esc_txt()( +    string      _txt, +  ) { +    string _unescape_sp_char_esc()(string _txt) { +      _txt = _txt +        .replaceAll(rgx.latex_special_char_escaped, +          format(q"┃%s┃", "$1")) +        .replaceAll(rgx.latex_special_char_escaped_braced, +          format(q"┃%s┃", "$1")); +      return _txt; +    } +    string _unescape_fontface_esc()(string _txt) { +      _txt = _txt.replaceAll(rgx.latex_identify_inline_fontface, +           format(q"┃%s%s┃", "$1", "$2")); +      return _txt; +    } +    _txt = replaceAll!(m => "\\" ~ m[1])(_txt, rgx.latex_special_char_for_escape); +    _txt = replaceAll!(m => "{\\" ~ m[1] ~ "}")(_txt, rgx.latex_special_char_for_escape_and_braces); +    _txt = replaceAll!(m => _unescape_sp_char_esc(m[0]))(_txt, rgx.latex_identify_inline_link); +    _txt = replaceAll!(m => _unescape_fontface_esc(m[0]))(_txt, rgx.latex_identify_inline_fontface); +    return _txt; +  } +  string fontface()( +    string      _txt, +  ) { +  _txt = _txt +    .replaceAll(rgx.inline_emphasis,    format(q"┃\begin{bfseries}%s\end{bfseries}┃", "$1")) +    .replaceAll(rgx.inline_bold,        format(q"┃\begin{bfseries}%s\end{bfseries}┃", "$1")) +    .replaceAll(rgx.inline_italics,     format(q"┃\emph{%s}┃",                        "$1")) +    .replaceAll(rgx.inline_italics,     format(q"┃\uline{%s}┃",                       "$1")) +    .replaceAll(rgx.inline_superscript, format(q"┃$$^{\textrm{%s}}$$┃",               "$1")) +    .replaceAll(rgx.inline_subscript,   format(q"┃$$_{\textrm{%s}}$$┃",               "$1")) +    .replaceAll(rgx.inline_strike,      format(q"┃\sout{%s}┃",                        "$1")) +    .replaceAll(rgx.inline_insert,      format(q"┃\uline{%s}┃",                       "$1")) +    .replaceAll(rgx.inline_mono,        format(q"┃\begin{monosp}%s\end{monosp}┃",     "$1")) +    .replaceAll(rgx.inline_italics,     format(q"┃``%s''┃",                           "$1")); +    return _txt; +  } +  string leading_hardspaces()( +    string      _txt, +  ) { +    string hardspaces(string _spaces) { +      _spaces  = _spaces +        .replaceAll(rgx.space, "\\hardspace "); +      return _spaces; +    } +    _txt = replaceAll!(m => hardspaces(m[0]))(_txt, rgx.spaces_line_start); +    return _txt; +  } +  string nbsp_char()(string _txt) { +    if (_txt.match(rgx.nbsp_char)) { +      _txt  = _txt.replaceAll(rgx.nbsp_char, "\\hardspace "); +    } +    return _txt; +  } +  string nbsp_char_to_space()(string _txt) { +    if (_txt.match(rgx.nbsp_char)) { +      _txt  = _txt.replaceAll(rgx.nbsp_char, " "); +    } +    return _txt; +  } +  string links_and_images(O,M)( +    string      _txt, +    const    O  obj, +             M  doc_matters, +  ) { +    if (obj.has.inline_links) { // TODO some images do not have inline links ... image without link +      string _width_adjust(string _width) { +        if (_width.to!int > 300) { _width = "300"; } // will need to vary max with papersize & orientation +        return _width; +      } +      string _latex_image_path(string _image_path) { +        auto pth_latex = DocReformPathsLaTeX(doc_matters); +        _image_path = pth_latex.latex_path_stuff ~ "/" ~ _image_path; +        return _image_path; +      } +      string _if_images(string _linked_content) { +        if (_linked_content.match(rgx.inline_image_info)) { +          _linked_content = replaceAll!(m => +              format(q"┃\includegraphics*[width=%spt]{%s}%s┃", +                _width_adjust(m[2]), _latex_image_path(m[1]), " \\\\\n") +            )(_linked_content, rgx.inline_image_info); +        } +        return _linked_content; +      } +      string _check_link(string _link) { +        _link = _link +          .replaceFirst(rgx.latex_clean_internal_link, "") +          .replaceAll(rgx.latex_special_char_for_escape_url, "\\$1"); +        return _link; +      } +      if  (obj.metainfo.is_a != "code") { +        _txt = replaceAll!(m => +            m[1] ~ "┤" ~ to!string((obj.stow.link[m[2].to!ulong])).encode ~ "├" +          )(_txt, rgx.inline_link_number_only); +        _txt = replaceAll!(m => +            ((m[1] == m[2]) && (m[2].match(rgx.uri))) +            ? format(q"┃\begin{scriptsize}\lefthalfcap\url{%s}\righthalfcup\end{scriptsize}┃", _check_link(m[1])) +            : (m[2].match(rgx.uri)) // ERROR +              ? format(q"┃%s\href{%s}%s{%s}┃", "\\\\\n", _check_link(m[2]), "\n", _if_images(m[1])) +              : format(q"┃\hyperlink{%s}{%s}┃", _check_link(m[2]), _if_images(m[1])) +          )(_txt, rgx.inline_link); +      } +    } +    return _txt; +  } +  string footnotes()( +    string      _txt, +  ) { +    if (_txt.match(rgx.inline_notes_al_gen)) { +      string _tex_note = q"┃\hypertarget{noteref_%s}{}\footnote[%s]{%% +  \label{note_%s}%s}┃"; +      _txt = _txt.replaceAll(rgx.inline_notes_al_regular_number_note, +        format(_tex_note, +          "$1", "$1", "$1", +          "$2".strip +        ).strip +      ); +    } +    return _txt; +  } +  string remove_footnotes()( +    string      _txt, +  ) { +    if (_txt.match(rgx.inline_notes_al_gen)) { +      _txt = replaceAll!(m => "")(_txt, rgx.inline_notes_al_gen); +    } +    return _txt; +  } +  string para(O)( +    string      _txt, +    O           obj, +  ) { +    if (obj.metainfo.is_of_type == "para") { +      string _tex_para; +      _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}%s┃"; +      _txt  = format(_tex_para, +        obj.metainfo.object_number, +        obj.metainfo.object_number, +        _txt.footnotes +      ).strip; +    } +    return _txt; +  } +  string bookindex(O)( +    string      _txt, +    O           obj, +  ) { +    if (obj.metainfo.is_of_type == "para" +      && obj.metainfo.is_a == "bookindex" +    ) { +      string _tex_para; +      _tex_para = q"┃%s┃"; +      _txt  = format(_tex_para, +        _txt.replaceAll(rgx.latex_clean_bookindex_linebreak, "\n") ~ "\n\\\\\n" +      ); +    } +    return _txt; +  } +  string heading(O,M)( +    string      _txt, +    O           obj, +    M           doc_matters, +    string      _part = "" +  ) { +    if (obj.metainfo.is_a == "heading") { +      string _tex_para; +      string _pg_break; +      string _sect; +      string _post; +      string _title_add; +      string _columns = ""; +      switch (obj.metainfo.heading_lev_markup) { +      case 0: // A == TITLE +        _pg_break = "\\begin{document}\n"; +        goto default; +      case 1: // B == part: section heading level +        _pg_break = "\\clearpage\n"; +        goto default; +      case 2: // C == part: section heading level +        _pg_break = "\\clearpage\n"; +        goto default; +      case 3: // D == part: section heading level +        _pg_break = "\\clearpage\n"; +        goto default; +      case 4: // 1 == section +        _columns = (_part != "bookindex") +          ? "" : "\n\\\\\n\\begin{multicols}{2}"; +        _pg_break = "\\clearpage\n"; +        _sect = "section"; +        _post = ""; +        _title_add = format(q"┃ +\markboth{%s}{%s}┃", +          doc_matters.conf_make_meta.meta.title_full, +          doc_matters.conf_make_meta.meta.title_full, +        ); +        goto default; +      case 5: // 2 == subsection +        _pg_break = ""; +        // _pg_break = "newpage"; // doubt this is necessary +        _sect = "subsection"; +        _post = " \\\n"; +        _title_add = ""; +        goto default; +      case 6: // 3 == subsubsection +        _pg_break = ""; +        // _pg_break = "newpage"; // doubt this is necessary +        _sect = "subsubsection"; +        _post = " \\\n"; +        _title_add = ""; +        goto default; +      default: +        if (obj.metainfo.heading_lev_markup == 0) { +          _tex_para = q"┃\begin{document} +\title{%s} +\author{ \textnormal{%s}} +\date{\begin{tiny}%s\end{tiny}} +\pagenumbering{roman}\maketitle +\pagestyle{fancy} +\newpage +\markboth{%s}{%s} +\\\\[3]\ \linebreak Copyright {\begin{small}{\copyright\end{small}} %s \\ +%s +\pagestyle{fancy} +\clearpage┃"; +          _txt = format(_tex_para, +            (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.creator_author).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.date_published).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.title_main).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.rights_copyright).sp_char_esc_txt, +            (doc_matters.conf_make_meta.meta.rights_license).sp_char_esc_txt, +          ); +        } else if (obj.metainfo.heading_lev_markup < 4) { +          _tex_para = q"┃%s\part*{\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}%s} +\addcontentsline{toc}{part}{%s} +\markboth{%s}┃"; +          _txt = format(_tex_para, +            _pg_break, +            obj.metainfo.object_number, +            obj.metainfo.object_number, +            _txt.strip.footnotes, +            _txt.strip.remove_footnotes, +            (doc_matters.conf_make_meta.meta.title_main).sp_char_esc_txt, +          ); +        } else if (obj.metainfo.heading_lev_markup > 3) { +          if (obj.metainfo.heading_lev_markup == 4 +          && _txt.match(regex(r"^Table of Contents$"))) { +            _tex_para = q"┃ +\pagenumbering{none} +\setcounter{page}{1} +\setlength{\parskip}{1ex plus0.5ex minus0.2ex} +\part*{\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{1}{1}\end{tiny}}}%s \newline %s} + +\clearpage +\markboth{%s}{%s} +\pagenumbering{gobble} +\renewcommand{\contentsname}{} +\tableofcontents +\markboth{%s}{%s} + +\clearpage +\pagenumbering{arabic} +\setcounter{page}{1} +\markboth{%s}{%s} +%% \null +\clearpage +\setcounter{page}{1}┃"; +            _txt = format(_tex_para, +              (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.creator_author).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_main).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_main).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +              (doc_matters.conf_make_meta.meta.title_full).sp_char_esc_txt, +            ); +          } else if (obj.metainfo.heading_lev_markup == 4 +            && _part == "bookindex" +            && _txt.match(regex(r"^Index$")) +          ) { +            _tex_para = q"┃%s\%s*{\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}%s} +\addcontentsline{toc}{%s}{%s%s}%s%s┃"; +            _txt = format(_tex_para, +              _pg_break, +              _sect.strip, +              obj.metainfo.object_number, +              obj.metainfo.object_number, +              _txt.footnotes.strip, +              _sect, +              _txt.remove_footnotes.strip, +              _post, +              _title_add, +              _columns, +            ); +          } else if (obj.metainfo.dummy_heading +            && obj.metainfo.heading_lev_markup == 4 +          ) { /+ dummy headings completely omitted +/ +            _txt = ""; +          } else { +            _tex_para = q"┃%s\%s*{\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}%s} +\addcontentsline{toc}{%s}{%s%s}%s┃"; +            _txt = format(_tex_para, +              _pg_break, +              _sect.strip, +              obj.metainfo.object_number, +              obj.metainfo.object_number, +              _txt.footnotes.strip, +              _sect, +              _txt.remove_footnotes.strip, +              _post, +              _title_add, +            ); +          } +        } +        break; +      } +    } +    return _txt.strip; +  } +string group(O,M)( +  string      _txt, +  O           obj, +  M           doc_matters, +) { +  if (obj.metainfo.is_a == "group") { +    string _tex_para; +    _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}\setlength{\parskip}{0.5ex plus0.2ex minus0.1ex} +\begin{footnotesize} +%s +\end{footnotesize} +┃"; +    _txt  = format(_tex_para, +      obj.metainfo.object_number, +      obj.metainfo.object_number, +      _txt.footnotes.strip +    ).strip; +  } +  return _txt; +} +string block(O,M)( +  string      _txt, +  O           obj, +  M           doc_matters, +) { +  if (obj.metainfo.is_a == "block") { +    // _txt = _txt.nbsp_char; +    string _tex_para; +    _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}\setlength{\parskip}{0.5ex plus0.2ex minus0.1ex} +\begin{footnotesize} +%s +\end{footnotesize} +\setlength{\parskip}{1ex plus0.5ex minus0.2ex} +┃"; // \hardspace +    /+ try both: +/ +    _txt = _txt.split(rgx.br_newlines_linebreaks).join("\n\n"); // _txt = _txt.split(rgx.br_newlines_linebreaks).join(" \\\n"); +    _txt  = format(_tex_para, +      obj.metainfo.object_number, +      obj.metainfo.object_number, +      _txt.nbsp_char.footnotes.strip +    ).strip; +  } +  return _txt; +} +string verse(O,M)( +  string      _txt, +  O           obj, +  M           doc_matters, +) { +  if (obj.metainfo.is_a == "verse") { +    string _tex_para; +    _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}\setlength{\parskip}{0.1ex plus0.1ex minus0.1ex} +\begin{footnotesize} + +%s + +\end{footnotesize} +\setlength{\parskip}{1ex plus0.5ex minus0.2ex} +\linebreak +┃"; // \hardspace +    _txt  = format(_tex_para, +      obj.metainfo.object_number, +      obj.metainfo.object_number, +      _txt.nbsp_char.footnotes.split("\n").join("\n\n").strip +    ).strip; +  } +  return _txt; +} +string codeblock(O,M)( +  string      _txt, +  O           obj, +  M           doc_matters, +) { +  if (obj.metainfo.is_a == "code") { +    string _tex_para; +    _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}}\setlength{\parskip}{0.5ex plus0.2ex minus0.1ex}\begin{Codeblock} +\begin{lstlisting} +%s +\end{lstlisting} +\end{Codeblock} +\setlength{\parskip}{1ex plus0.5ex minus0.2ex} +┃"; +    _txt  = format(_tex_para, +      obj.metainfo.object_number, +      obj.metainfo.object_number, +      _txt.nbsp_char_to_space +    ).strip; +  } +  return _txt; +} +auto tablarize(O)( +  string            _txt, +  const        O    obj, +) { +  string[] _table_rows = (_txt).split(rgx.table_delimiter_row); +  string[] _table_cols; +  string _table; +  string _tablenote; +  foreach(row_idx, row; _table_rows) { +    _table_cols = row.split(rgx.table_delimiter_col); +      _table ~= ""; +      foreach(col_idx, cell; _table_cols) { +        if ((_table_cols.length == 1) +        && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx) +          _tablenote ~= cell; +        } else { +          // // _table ~= "\\bfseries "; +          // _table ~= cell; +          // _table ~= (_table_cols.length > (col_idx + 1)) ? "&" : ""; +          _table ~= format(q"┃%s%s┃", +            cell, +            (_table_cols.length > (col_idx + 1)) ? "&" : "" +          ); +        } +      } +      _table ~= "\\\\"; +    } +  auto t = tuple( +    _table, +    _tablenote, +  ); +  return t; +} +string table(O,M)( +  string      _txt, +  O           obj, +  M           doc_matters, +) { +  if (obj.metainfo.is_a == "table") { +    auto _t = _txt.tablarize(obj); +    string _table = _t[0]; +    string _t_n = _t[1]; +    string papertype = "a4"; +    uint pw = 0; +    switch (papertype) { +    case "a4":     pw = (paper.a4.portrait.w     - 20); break; +    case "a5":     pw = (paper.a5.portrait.w     - 20); break; +    case "b4":     pw = (paper.b4.portrait.w     - 20); break; +    case "letter": pw = (paper.letter.portrait.w - 20); break; +    case "legal":  pw = (paper.legal.portrait.w  - 20); break; +    default:       pw = 0;                              break; +    } +    // auto textwidth = (pw - 24); +    string _colw = ""; +    foreach (w; obj.table.column_widths) { +      _colw ~= format(q"┃p{%.0fmm}┃", +        (w * pw / 100) +        // (w * (pw - 24)/ 100) +        // (w * textwidth / 100) +      ); +    } +    string _tex_para; +    _tex_para = q"┃\begin{tiny}\hspace{0mm}\end{tiny}{\marginpar{\begin{tiny}\hspace{0mm}\hypertarget{%s}{%s}\end{tiny}}} +\setlength{\LTleft}{0pt} +\setlength{\LTright}{\fill} +\begin{tiny} +\begin{longtable}{%s} +%s +\end{longtable} +\end{tiny} +┃"; +    _txt  = format(_tex_para, +      obj.metainfo.object_number, +      obj.metainfo.object_number, +      _colw, +      _table, +    ).strip; +  } +  return _txt; +} +  string bullets_and_indentation(O)( +    string      _txt, +    O           obj, +  ) { +    string _tex_para; +    string _hang; string _indent; +    int _paper_margin = -10; +    int _indent_increment = 8; // 5; 10; +    if (obj.attrib.bullet) { +      int _bullet_space = 5; +      _indent = ((obj.attrib.indent_base * _indent_increment) + _paper_margin + _bullet_space).to!string; +      _txt  = format(q"┃\begin{Bullet}{%smm}$\txtbullet$\hspace{\enspace}%s\end{Bullet}┃", +        _indent, +        _txt.footnotes +      ).strip; +    } else if ( +      obj.attrib.indent_base != 0 +      && obj.attrib.indent_base == obj.attrib.indent_hang +    ) { +      _indent = ((obj.attrib.indent_base * _indent_increment) + _paper_margin).to!string; +      _tex_para = q"┃\begin{ParagraphIndent}{%smm}%s \end{ParagraphIndent}┃"; +      _txt = format(_tex_para, +        _indent, +        _txt.footnotes +      ).strip; +    } else if ( +      obj.attrib.indent_base != 0 +      || obj.attrib.indent_hang != 0 +    ) { +      _indent = ((obj.attrib.indent_base * _indent_increment) + _paper_margin).to!string; +      _hang = (((obj.attrib.indent_hang - obj.attrib.indent_base) * _indent_increment)).to!string; +      _txt = format(q"┃\begin{ParagraphHang}{%smm}{%smm}%s \end{ParagraphHang}┃", +        _indent, _hang, +        _txt.footnotes +      ).strip; +    } +    return _txt; +  } +  string latex_head(M)( +                          M    doc_matters, +  ) { +    struct paperType { +      string a4_portrait; +      string a4_landscape; +      string us_letter_portrait; +      string us_letter_landscape; +    } +    auto paper           = paperType(); +    paper.a4_portrait    = format(q"┃ +\documentclass[12pt,a4paper,titlepage]{scrartcl} +\setlength{\textheight}{228mm} \setlength{\textwidth}{160mm} +┃", +  ); +  paper.a4_landscape    = format(q"┃ +\documentclass[11pt,a4paper,landscape,titlepage,twocolumn]{scrartcl} +\setlength{\textheight}{160mm} \setlength{\textwidth}{238mm} +┃", +  ); +  paper.us_letter_portrait    = format(q"┃ +\documentclass[12pt,letterpaper,titlepage]{scrartcl} +\setlength{\textheight}{212mm} \setlength{\textwidth}{166mm} +┃", +  ); +  paper.us_letter_landscape    = format(q"┃ +\documentclass[11pt,letterpaper,landscape,titlepage,twocolumn]{scrartcl} +\setlength{\textheight}{166mm} \setlength{\textwidth}{226mm} +┃", +  ); +  struct paperMargins { +    string portrait; +    string landscape; +  } +  auto margins           = paperMargins(); +  margins.portrait    = format(q"┃ +\setlength{\oddsidemargin}{0mm} \setlength{\evensidemargin}{0mm} +\setlength{\topmargin}{-12pt} \setlength{\headheight}{12pt} +\setlength{\headsep}{35pt} +┃", +  ); +  margins.landscape    = format(q"┃ +\setlength{\oddsidemargin}{6mm} \setlength{\evensidemargin}{6mm} +\setlength{\topmargin}{-12mm} \setlength{\headheight}{12pt} +\setlength{\headsep}{20pt} +┃", +  ); +  struct columnsMulti { +    string portrait; +    string landscape; +  } +  auto multicol           = columnsMulti(); +  multicol.portrait    = format(q"┃ +\usepackage{multicol} +┃", +  ); +  multicol.landscape    = ""; +  struct colorLinks { +    string mono; +    string color; +  } +  auto links           = colorLinks(); +  links.mono    = format(q"┃ +\usepackage[xetex, +  colorlinks=true, +  urlcolor=myblack, +  filecolor=myblack, +  linkcolor=myblack, +┃", +  ); +  links.color    = format(q"┃ +\usepackage[xetex, +  colorlinks=true, +  urlcolor=myblue,    %% \href{...}{...}   external url +  filecolor=mygreen,  %% \href{...}        local file +  linkcolor=myred,    %% \href{...} and \pageref{...} +  ┃", +    ); +    string _latex_head = format(q"┃%%%% DocReform LaTeX output +%%%% Generated by: %s +%%%% D version: ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux-gnu] +%%%% LaTeX output +%%%% Last Generated on: +%%%% SiSU http://www.jus.uio.no/sisu +%s +%s +\setlength{\marginparsep}{4mm} +\setlength{\marginparwidth}{8mm} +%s +\usepackage{polyglossia, ucs, fontspec, xltxtra, xunicode} +\setmainlanguage{english} +\setotherlanguage{} +\setmainfont{Liberation Sans} +\setmonofont[Scale=0.85]{Liberation Mono} +\usepackage{alltt} +\usepackage{thumbpdf} +%s +  pdftitle={%s}, +  pdfauthor={%s}, +  pdfsubject={%s}, +  pdfkeywords={}, +  pageanchor=true, +  plainpages=true, +  pdfpagelabels=true, +  pagebackref, +  bookmarks=true, +  bookmarksopen=true, +  pdfmenubar=true, +  pdfpagemode=UseOutline, +  pdffitwindow=true, +  pdfwindowui=true, +  plainpages=false, +  pdfstartview=FitH +] +{hyperref} +\usepackage[usenames]{color} +\definecolor{myblack}{rgb}{0,0,0} +\definecolor{myred}{rgb}{0.75,0,0} +\definecolor{mygreen}{rgb}{0,0.5,0} +\definecolor{myblue}{rgb}{0,0,0.5} +\definecolor{mywhite}{rgb}{1,1,1} +\usepackage{url} +\urlstyle{sf} +\usepackage{textcomp} +\usepackage[parfill]{parskip} +\usepackage[normalem]{ulem} +\usepackage{soul} +\usepackage{longtable} +\usepackage[tc]{titlepic} +\usepackage{graphicx} +\makeatletter +\parindent0pt +\usepackage{amssymb} +\usepackage{listings} +\usepackage{color} +\usepackage{textcomp} +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{4} +\makeatletter +\usepackage[multiple,ragged]{footmisc} +\setlength\footnotemargin{12pt} +\usepackage[para]{manyfoot} +\DeclareNewFootnote{A} +\newenvironment{ParagraphIndent}[1]%% +{ +\begin{list}{}{%% +\setlength\topsep{0pt}%% +\addtolength{\leftmargin}{#1} +\setlength\parsep{0pt plus 1pt}%% +} +\item[] +} +{\end{list}} +\newenvironment{ParagraphHang}[2]%% +{ +\begin{list}{}{%% +\setlength\topsep{0pt}%% +\addtolength{\leftmargin}{#1} +\itemindent=#2 +\setlength\parsep{0pt plus 1pt}%% +} +\item[] +} +{\end{list}} +\newenvironment{Bullet}[1]%% +{ +\begin{list}{}{%% +\setlength\topsep{0pt}%% +\addtolength{\leftmargin}{#1} +\itemindent=-1em +\setlength\parsep{0pt plus 1pt}%% +} +\item[] +} +{\end{list}} +\usepackage{fancyhdr} +\lhead{} +\renewcommand{\part}{\@startsection +  {part}{1}{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\bfseries\large\upshape\raggedright}} +\renewcommand{\section}{\@startsection +  {section}{2}{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\bfseries\large\upshape\raggedright}} +\renewcommand{\subsection}{\@startsection +  {subsection}{3}{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\bfseries\large\upshape\raggedright}} +\renewcommand{\subsubsection}{\@startsection +  {subsubsection}{4}{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\normalfont\normalsize\bfseries\raggedright}} +\renewcommand{\paragraph}{\@startsection +  {paragraph}{5}{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\normalfont\normalsize\itshape\raggedright}} +\renewcommand{\subparagraph}{\@startsection +  {subparagraph}%%{6}%%{-2mm}%% +  {-\baselineskip}{0.5\baselineskip}%% +  {\normalfont\normalsize\itshape\raggedright}} +\selectlanguage{english} +\lhead[ ]{ } +\chead[ \fancyplain{} \bfseries \footnotesize \leftmark ]{ \fancyplain{} \bfseries \footnotesize \rightmark } +\rhead[ ]{ } +\lfoot[\textrm{\thepage}]{\tiny \href{http://sisudoc.org}{SiSU}} +\cfoot{\href{http://git.sisudoc.org}{git}} +\rfoot[\tiny \href{}{}]{\textrm{\thepage}} +\tolerance=300 +\clubpenalty=300 +\widowpenalty=300 +\makeatother +\makeatother +\chardef\txtbullet="2022 +\chardef\tilde="7E +\def\asterisk{{\rm \char42} } +\definecolor{Light}{gray}{.92} +\newcommand{\Codeblock}[1]{\normaltext\raggedright\small\ttfamily\texbackslash#1} +\newcommand{\monosp}[1]{\normaltext\ttfamily\texbackslash#1} +\newcommand{\parasep}{\\ \begin{center}*\hspace{2em}*\hspace{2em}*\end{center} \\} +\newcommand{\hardspace}{{~}} +\newcommand{\caret}{{\^{~}}} +\newcommand{\pipe}{{\textbar}} +\newcommand{\curlyopen}{{} +\newcommand{\curlyclose}{}} +\newcommand{\lt}{{UseTextSymbol{OML}{<}}} +\newcommand{\gt}{{UseTextSymbol{OML}{>}}} +\newcommand{\slash}{{/}} +\newcommand{\underscore}{\_} +\newcommand{\exclaim}{\Verbatim{!}} +\definecolor{listinggray}{gray}{0.9} +\definecolor{lbcolor}{rgb}{0.9,0.9,0.9} +\lstset{ +  backgroundcolor=\color{lbcolor}, +  tabsize=4, +  rulecolor=, +  language=, +  basicstyle=\scriptsize, +  upquote=true, +  aboveskip={1.5\baselineskip}, +  columns=fixed, +  showstringspaces=false, +  extendedchars=true, +  breaklines=true, +  prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}}, +  frame=single, +  showtabs=false, +  showspaces=false, +  showstringspaces=false, +  identifierstyle=\ttfamily, +  keywordstyle=\color[rgb]{0,0,1}, +  commentstyle=\color[rgb]{0.133,0.545,0.133}, +  stringstyle=\color[rgb]{0.627,0.126,0.941}, +} +  ┃", +    doc_matters.opt.action.debug_do ? "" : doc_matters.generator_program.name_and_version.strip, +    paper.a4_portrait.strip, +    margins.portrait.strip, +    multicol.portrait.strip, +    links.mono.strip, // links.color.strip, +    doc_matters.conf_make_meta.meta.title_full.strip, +    doc_matters.conf_make_meta.meta.creator_author.strip, +    doc_matters.conf_make_meta.meta.classify_subject.strip, +  ); +    return _latex_head.strip; +  } +  string latex_body(D,M)( +    const    D   doc_abstraction, +             M   doc_matters, +  ) { +    string _latex_body = ""; +    bool _multicolumns = false; +    string _txt; +    foreach (part; doc_matters.has.keys_seq.latex) { +      foreach (obj; doc_abstraction[part]) { +        switch (obj.metainfo.is_of_part) { +        case "frontmatter":              assert(part == "head" || "toc"); +          _txt = obj.text +            .sp_char_esc(obj) +            .fontface; +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              _txt = _txt.heading(obj, doc_matters); +              goto default; +            case "toc": +              break; +            default: +              _latex_body ~= _txt ~ "\n\n"; +              _txt = ""; +              break; +            } +            break; +          default: break; +          } +          break; +        case "body":                     assert(part == "body" || "head"); // surprise +          _txt = obj.text +            .sp_char_esc(obj) +            .fontface; +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              _txt = _txt.heading(obj, doc_matters); +              goto default; +            case "para": +              _txt = _txt.para(obj) +                .bullets_and_indentation(obj) +                .links_and_images(obj, doc_matters); +              goto default; +            default: +              _latex_body ~= _txt ~ "\n\n"; +              _txt = ""; +              break; +            } +            break; +          case "block": +            switch (obj.metainfo.is_a) { +            case "quote": +              goto default; // TODO +            case "group": +              /+ (hardspaces not honored) [remove any hardspace marker] +/ +              _txt = _txt.group(obj, doc_matters) +                .links_and_images(obj, doc_matters); +              goto default; +            case "block": +              /+ (hardspace honored) \hardspace +/ +              _txt = _txt.block(obj, doc_matters) +                .links_and_images(obj, doc_matters); +              goto default; +            case "verse": +              /+ (hardspace honored) \hardspace +/ +              _txt = _txt.verse(obj, doc_matters) +                .links_and_images(obj, doc_matters); +              goto default; +            case "code": +              /+ (hardspace honored) \begin{lstlisting} clear hardspace marker +/ +              _txt = _txt.codeblock(obj, doc_matters); +              goto default; +            case "table": +              _txt = _txt.table(obj, doc_matters); +              goto default; // TODO +            default: +              _latex_body ~= _txt ~ "\n\n"; +              _txt = ""; +              break; +            } +            break; +          default: break; +          } +          break; +        case "backmatter": +          assert(part == "endnotes" || "glossary" || "bibliography" || "bookindex" || "blurb" || "tail"); +          _txt = obj.text +            .sp_char_esc(obj) +            .fontface; +          switch (obj.metainfo.is_of_type) { +          case "para": +            if (part != "bookindex" && _multicolumns) { +              _multicolumns = false; +              _latex_body ~= "\n\\end{multicols}\n"; +            } +            switch (obj.metainfo.is_a) { +            case "heading": +              if (part == "bookindex") { +                _multicolumns = true; +              } +              _txt = _txt.heading(obj, doc_matters, part); +              goto default; +            case "endnote":              assert(part == "endnotes"); +              _txt = _txt.para(obj) +                .bullets_and_indentation(obj) +                .links_and_images(obj, doc_matters); +              goto default; +            case "glossary":             assert(part == "glossary"); +              _txt = _txt.para(obj) +                .bullets_and_indentation(obj) +                .links_and_images(obj, doc_matters); +              goto default; +            case "bibliography":         assert(part == "bibliography"); +              _txt = _txt.para(obj) +                .bullets_and_indentation(obj); +              goto default; +            case "bookindex":            assert(part == "bookindex"); +              /+ two column, special section +/ +              _txt = _txt.bookindex(obj) +                .links_and_images(obj, doc_matters); +              goto default; +            case "blurb":                assert(part == "blurb"); +              _txt = _txt.para(obj) +                .bullets_and_indentation(obj) +                .links_and_images(obj, doc_matters); +              goto default; +            default: +              _latex_body ~= (part == "bookindex" && obj.metainfo.is_a != "heading") +                ? _txt : (_txt ~ "\n\n"); +              _txt = ""; +              break; +            } +            break; +          default: break; +          } +          break; +        case "comment": +          break; +        default: +          { /+ debug +/ +            if (doc_matters.opt.action.debug_do +            && doc_matters.opt.action.verbose) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              writeln(__FILE__, ":", __LINE__, ": ", obj.text); +            } +          } +          break; +        } +      } +    } +    if (_multicolumns) { +      _multicolumns = false; +      _latex_body ~= "\n\\end{multicols}\n"; +    } +    return _latex_body; +  } +  string latex_tail(M)( +                          M    doc_matters, +  ) { +    string _latex_tail = format(q"┃ + +\end{document} +  ┃", +    // doc_matters.conf_make_meta.meta.title_full, +    // doc_matters.conf_make_meta.meta.creator_author, +  ); +    return _latex_tail; +  } +  void writeOutputLaTeX(T,M)( +    const T    latex_content, +          M    doc_matters, +  ) { +    auto pth_latex = DocReformPathsLaTeX(doc_matters); +    try { +      { /+ debug +/ +        if (doc_matters.opt.action.debug_do +        && doc_matters.opt.action.verbose) { +          writeln(latex_content.head); +          writeln(latex_content.content); +          writeln(latex_content.tail); +        } +      } +      if (!exists(pth_latex.latex_path_stuff)) { +        (pth_latex.latex_path_stuff).mkdirRecurse; +      } +      writeln(pth_latex.latex_file_with_path); +      auto f = File(pth_latex.latex_file_with_path, "w"); +      f.writeln(latex_content.head); +      f.writeln(latex_content.content); +      f.writeln(latex_content.tail); +      foreach (image; doc_matters.srcs.image_list) { +        auto fn_src_in = doc_matters.src.image_dir_path ~ "/" ~ image; +        auto fn_src_out_file = pth_latex.latex_path_stuff ~ "/" ~ image; +        if (exists(fn_src_in)) { +          fn_src_in.copy(fn_src_out_file); +        } +      } +    } catch (ErrnoException ex) { +      // handle error +    } +  } +  void outputLaTeX(D,M)( +    const    D   doc_abstraction, +             M   doc_matters, +  ) { +    struct LaTeX { +      string head; +      string content; +      string tail; +    } +    auto latex           = LaTeX(); +    latex.head           = latex_head(doc_matters); +    latex.content        = latex_body(doc_abstraction, doc_matters); +    latex.tail           = latex_tail(doc_matters); +    latex.writeOutputLaTeX(doc_matters); +  } +} diff --git a/src/doc_reform/output/paths_output.d b/src/doc_reform/output/paths_output.d index 615a666..305aa17 100644 --- a/src/doc_reform/output/paths_output.d +++ b/src/doc_reform/output/paths_output.d @@ -331,6 +331,35 @@ template DocReformPathsODT() {      return _PathsStruct();    }  } +template DocReformPathsLaTeX() { +  mixin DocReformRgxInit; +  static auto rgx = Rgx(); +  auto DocReformPathsLaTeX(M)( +    M  doc_matters, +  ) { +    struct _PathsStruct { +      string base_filename(string fn_src) { +        return fn_src.baseName.stripExtension; +      } +      string base() { +        auto out_pth = DocReformOutPaths!()(doc_matters.output_path, doc_matters.src.language); +        string base_dir = "latex"; +        return asNormalizedPath((out_pth.output_root).chainPath(base_dir)).array; +      } +      string latex_path_stuff() { +        return asNormalizedPath(base.chainPath(base_filename(doc_matters.src.filename))).array; +      } +      string latex_file_with_path() { +        return asNormalizedPath(base.chainPath(base_filename(doc_matters.src.filename) ~ "." ~ doc_matters.src.language ~ ".tex")).array; +      } +      string images() { +        string image_dir = "image"; +        return asNormalizedPath((base).chainPath(image_dir)).array; +      } +    } +    return _PathsStruct(); +  } +}  template DocReformPathsSQLiteDiscrete() {    mixin DocReformRgxInit;    static auto rgx = Rgx(); diff --git a/src/doc_reform/output/rgx.d b/src/doc_reform/output/rgx.d index c9e9516..5ab71f9 100644 --- a/src/doc_reform/output/rgx.d +++ b/src/doc_reform/output/rgx.d @@ -132,5 +132,17 @@ static template DocReformOutputRgxInit() {      static xhtml_less_than                            = ctRegex!(`[<]`, "m");      // <      static xhtml_greater_than                         = ctRegex!(`[>]`, "m");      // >      static xhtml_line_break                           = ctRegex!(` [\\]{2}`, "m"); // <br /> +    static latex_special_char_shortlist               = ctRegex!(`([%$_#&\\])`); +    static latex_special_char_curlybraces             = ctRegex!(`([{}])`); +    static latex_special_char                         = ctRegex!(`([%${}_#&\\])`); +    static latex_special_char_for_escape              = ctRegex!(`([%${}_#\\])`); +    static latex_special_char_for_escape_and_braces   = ctRegex!(`([&])`); +    static latex_special_char_for_escape_url          = ctRegex!(`([%])`); +    static latex_special_char_escaped                 = ctRegex!(`\\([%${}_#\\])`); +    static latex_special_char_escaped_braced          = ctRegex!(`[{]\\([&])[}]`); +    static latex_identify_inline_link                 = ctRegex!(`┥.+?┝┤\S+?├`, "mg"); +    static latex_clean_internal_link                  = ctRegex!(`^(?:#|¤\S+?#)`, "m"); +    static latex_identify_inline_fontface             = ctRegex!(`\\([_#$]┨.+?┣)\\([_#$])`, "mg"); +    static latex_clean_bookindex_linebreak            = ctRegex!(`\s*\\\\\\\\\s*`, "m");    }  } | 
