-*- mode: org -*- #+TITLE: spine (doc_manifest) metadata (document curate) #+DESCRIPTION: documents - structuring, publishing in multiple formats & search #+FILETAGS: :spine:output:metadata: #+AUTHOR: Ralph Amissah #+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] #+COPYRIGHT: Copyright (C) 2015 - 2023 Ralph Amissah #+LANGUAGE: en #+STARTUP: content hideblocks hidestars noindent entitiespretty #+PROPERTY: header-args :exports code #+PROPERTY: header-args+ :noweb yes #+PROPERTY: header-args+ :results no #+PROPERTY: header-args+ :cache no #+PROPERTY: header-args+ :padline no #+PROPERTY: header-args+ :mkdirp yes #+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t - [[./doc-reform.org][doc-reform.org]] [[./][org/]] * document curate _summary_ :module:spine:metadoc_show_summary: ** _module template_ metadoc document metadata #+HEADER: :tangle "../src/doc_reform/io_out/metadata.d" #+HEADER: :noweb yes #+BEGIN_SRC d <<doc_header_including_copyright_and_license>> module doc_reform.io_out.metadata; template outputMetadata() { @safe void outputMetadata(T)( T doc_matters) { <<curated_html_search>> <<output_imports>> <<curated_html_themes_0>> <<curated_html_themes_1>> <<curated_topics_html_head_1>> <<curated_html_head>> <<curated_topics_html_head_2>> <<curated_topics_html_head_theme>> <<output_metadata_write>> <<output_metadata>> } } #+END_SRC ** imports #+NAME: output_imports #+BEGIN_SRC d import std.file, std.format; import doc_reform.io_out; mixin InternalMarkup; string[] metadata_; #+END_SRC ** metadata #+NAME: output_metadata #+BEGIN_SRC d static auto mkup = InlineMarkup(); if (doc_matters.opt.action.debug_do) { writeln(doc_matters.src.filename_base); writeln("Title: ", doc_matters.conf_make_meta.meta.title_full); writeln(" Author: ", doc_matters.conf_make_meta.meta.creator_author); writeln(" Published: ", doc_matters.conf_make_meta.meta.date_published); writeln(" Copyright: ", doc_matters.conf_make_meta.meta.rights_copyright); writeln(" License: ", doc_matters.conf_make_meta.meta.rights_license); if (doc_matters.conf_make_meta.meta.classify_topic_register_arr.length > 0) { foreach (topic; doc_matters.conf_make_meta.meta.classify_topic_register_arr.sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)) { string[] subject_tree = topic.split(mkup.sep); if (subject_tree.length > 0) { writeln(" ", subject_tree[0]); } if (subject_tree.length > 1) { writeln(" ", subject_tree[1]); } if (subject_tree.length > 2) { writeln(" ", subject_tree[2]); } if (subject_tree.length > 3) { writeln(" ", subject_tree[3]); } if (subject_tree.length > 4) { writeln(" ", subject_tree[4]); } } } } auto pth_html = spinePathsHTML!()(doc_matters.output_path, doc_matters.src.language); auto pth_epub = spinePathsEPUB!()(doc_matters.output_path, doc_matters.src.language); auto pth_pdf = spinePathsPDF!()(doc_matters); auto pth_pod = spinePathsPods!()(doc_matters); metadata_ ~= format(q"┃<body lang="en" xml:lang="en"> <a name="top" id="top"></a> <a name="up" id="up"></a> <a name="start" id="start"></a> ┃"); metadata_ ~= "<div class=\"flex-menu-bar\"><div class=\"flex-menu-option\">"; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= format(q"┃<p>[<a href="../../../index.html"> <b>≅</b> HOME </a>] Curated metadata: [<a href="../../authors.html"> Authors </a>] [<a href="../../topics.html"> Topics </a>]</p> ┃"); } else { metadata_ ~= format(q"┃<p>[<a href="../../../index.html"> ≅ <b>HOME</b> </a>] ┃"); } metadata_ ~= "</div>" ~ inline_search_form(doc_matters) ~ "</div><hr />"; if (!(doc_matters.conf_make_meta.meta.title_full.empty)) { metadata_ ~= "<p class=\"lev0\">Title: <b><a href=\"" ~ doc_matters.src.filename_base ~ "/toc.html\">" ~ doc_matters.conf_make_meta.meta.title_full ~ "</a></b></p>"; } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt2) { writeln("ERROR no Title information provided in document header ", doc_matters.src.filename_base); } if (!(doc_matters.conf_make_meta.meta.creator_author.empty)) { if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev1\">Author: <b><a href=\"../../authors.html#" ~ doc_matters.conf_make_meta.meta.creator_author_surname.translate([' ' : "_"]) ~ "\">" ~ doc_matters.conf_make_meta.meta.creator_author ~ "</a></b></p>"; } else { metadata_ ~= "<p class=\"lev1\">Author: <b>" ~ doc_matters.conf_make_meta.meta.creator_author ~ "</b></p>"; } } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt2) { writeln("ERROR no Author information provided in document header ", doc_matters.src.filename_base); } metadata_ ~= "<p class=\"lev1\">Published: " ~ doc_matters.conf_make_meta.meta.date_published ~ "</p>"; if (!(doc_matters.conf_make_meta.meta.rights_copyright.empty)) { metadata_ ~= "<p class=\"lev1\">Copyright: " ~ doc_matters.conf_make_meta.meta.rights_copyright ~ "</p>"; } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt2) { writeln("WARNING no Copyright information provided in document header ", doc_matters.src.filename_base); } if (!(doc_matters.conf_make_meta.meta.rights_license.empty)) { metadata_ ~= "<p class=\"lev1\">License: " ~ doc_matters.conf_make_meta.meta.rights_license ~ "</p>"; } else if (doc_matters.opt.action.debug_do || doc_matters.opt.action.vox_gt2) { writeln("WARNING no License information provided in document header ", doc_matters.src.filename_base); } if (!(doc_matters.conf_make_meta.meta.notes_summary.empty)) { metadata_ ~= "<hr /><p class=\"lev0\">Summary:</p><p class=\"lev1\">" ~ doc_matters.conf_make_meta.meta.notes_summary ~ "</p>"; } else if (doc_matters.opt.action.debug_do) { writeln("WARNING no summary of text provided in document header ", doc_matters.src.filename_base); } metadata_ ~= "<hr /><p class=\"lev1\">source: " ~ doc_matters.src.filename_base ~ "</p>"; if (doc_matters.opt.action.html_link_markup_source) { metadata_ ~= "<p class=\"lev1\">● markup source: [<a href=\"../../" ~ pth_pod.internal_base ~ "/" ~ doc_matters.src.filename_base ~ ".zip\">" ~ " zipped pod </a>] " ~ "[<a href=\"../../" ~ pth_pod.internal_base ~ "/" ~ doc_matters.src.filename_base ~ "/\">" ~ " pod tree </a>]"; } metadata_ ~= "<p class=\"lev1\">● outputs: [<a href=\"" ~ doc_matters.src.filename_base ~ ".html\">" ~ " ▣ html scroll </a>] " ~ "[<a href=\"" ~ doc_matters.src.filename_base ~ "/toc.html\">" ~ " ▤ html seg </a>]" ~ "[<a href=\"../../" ~ pth_epub.internal_base ~ "/" ~ doc_matters.src.filename_base ~ "." ~ doc_matters.src.language ~ ".epub\">" ~ " ◆ epub </a>]"; if ((doc_matters.opt.action.html_link_pdf) || (doc_matters.opt.action.html_link_pdf_a4)) { metadata_ ~= "[<a href=\"../../pdf/" ~ doc_matters.src.filename_base ~ "." ~ doc_matters.src.language ~ ".a4.portrait.pdf\">" ~ " □ pdf (a4) </a>]"; } if ((doc_matters.opt.action.html_link_pdf) || (doc_matters.opt.action.html_link_pdf_letter)) { metadata_ ~= "[<a href=\"../../pdf/" ~ doc_matters.src.filename_base ~ "." ~ doc_matters.src.language ~ ".letter.portrait.pdf\">" ~ " □ pdf (U.S. letter) </a>]"; } metadata_ ~= "</p>"; if (doc_matters.conf_make_meta.meta.classify_topic_register_arr.length > 0) { metadata_ ~= "<hr /><p class=\"lev0\">Topics:</p>"; string[] _top = ["", "", "", "", ""]; foreach (topic; doc_matters.conf_make_meta.meta.classify_topic_register_arr.sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)) { string[] subject_tree = topic.split(mkup.sep); if (subject_tree.length > 0) { if (subject_tree[0] != _top[0]) { _top[0] = subject_tree[0]; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev1\"><a href=\"../../topics.html#" ~ subject_tree[0].translate([' ' : "_"]) ~ "\">" ~ subject_tree[0] ~ "</a></p>"; } else { metadata_ ~= "<p class=\"lev1\">" ~ subject_tree[0] ~ "</p>"; } } if (subject_tree.length > 1) { if (subject_tree[1] != _top[1]) { _top[1] = subject_tree[1]; _top[2] = ""; _top[3] = ""; _top[4] = ""; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev2\"><a href=\"../../topics.html#" ~ subject_tree[0].translate([' ' : "_"]) ~ "." ~ subject_tree[1].translate([' ' : "_"]) ~ "\">" ~ subject_tree[1] ~ "</a></p>"; } else { metadata_ ~= "<p class=\"lev2\">" ~ subject_tree[1] ~ "</p>"; } } if (subject_tree.length > 2) { if (subject_tree[2] != _top[2]) { _top[2] = subject_tree[2]; _top[3] = ""; _top[4] = ""; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev3\"><a href=\"../../topics.html#" ~ subject_tree[0].translate([' ' : "_"]) ~ "." ~ subject_tree[1].translate([' ' : "_"]) ~ "." ~ subject_tree[2].translate([' ' : "_"]) ~ "\">" ~ subject_tree[2] ~ "</a></p>"; } else { metadata_ ~= "<p class=\"lev3\">" ~ subject_tree[2] ~ "</p>"; } } if (subject_tree.length > 3) { if (subject_tree[3] != _top[3]) { _top[3] = subject_tree[3]; _top[4] = ""; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev4\"><a href=\"../../topics.html#" ~ subject_tree[0].translate([' ' : "_"]) ~ "." ~ subject_tree[1].translate([' ' : "_"]) ~ "." ~ subject_tree[2].translate([' ' : "_"]) ~ "." ~ subject_tree[3].translate([' ' : "_"]) ~ "\">" ~ subject_tree[3] ~ "</a></p>"; } else { metadata_ ~= "<p class=\"lev4\">" ~ subject_tree[3] ~ "</p>"; } } if (subject_tree.length > 4) { if (subject_tree[4] != _top[4]) { _top[4] = subject_tree[4]; if (doc_matters.opt.action.html_link_curate) { metadata_ ~= "<p class=\"lev5\"><a href=\"../../topics.html#" ~ subject_tree[0].translate([' ' : "_"]) ~ "." ~ subject_tree[1].translate([' ' : "_"]) ~ "." ~ subject_tree[2].translate([' ' : "_"]) ~ "." ~ subject_tree[3].translate([' ' : "_"]) ~ "." ~ subject_tree[4].translate([' ' : "_"]) ~ "\">" ~ subject_tree[4] ~ "</a></p>"; } else { metadata_ ~= "<p class=\"lev5\">" ~ subject_tree[4] ~ "</p>"; } } } } } } } } } else if (doc_matters.opt.action.debug_do) { writeln("WARNING no topic_register classification of text provided in document header ", doc_matters.src.filename_base); } metadata_write_output(doc_matters, metadata_); #+END_SRC ** metadata write output #+NAME: output_metadata_write #+BEGIN_SRC d @safe void metadata_write_output(M)(M doc_matters, string[] metadata_) { auto pth_html = spinePathsHTML!()(doc_matters.output_path, doc_matters.src.language); try { if (!exists(pth_html.base)) { pth_html.base.mkdirRecurse; } auto f = File(pth_html.fn_scroll("metadata." ~ doc_matters.src.filename), "w"); foreach (o; metadata_) { f.writeln(o); } } catch (ErrnoException ex) { // Handle error } if (doc_matters.opt.action.vox_gt0) { writeln(" ", pth_html.fn_scroll("metadata." ~ doc_matters.src.filename)); } } #+END_SRC *** themes **** head #+NAME: curated_html_themes_0 #+BEGIN_SRC css string theme_dark_0 = format(q"┃ body { color : #CCCCCC; background : #000000; background-color : #000000; } a:link { color : #FFFFFF; text-decoration : none; } a:visited { color : #999999; text-decoration : none; } a:hover { color : #000000; background-color : #555555; } a:hover img { background-color : #000000; } a:active { color : #888888; text-decoration : underline; } input { color : #FFFFFF; background-color : #777777; } ┃"); string theme_light_0 = format(q"┃ body { color : #000000; background : #FFFFFF; background-color : #FFFFFF; } a:link { color : #003399; text-decoration : none; } a:visited { color : #003399; text-decoration : none; } a:hover { color : #000000; background-color : #f9f9aa; } a:hover img { background-color : #FFFFFF; } a:active { color : #003399; text-decoration : underline; } input { color : #000000; background-color : #FFFFFF; } ┃"); #+END_SRC **** levels #+NAME: curated_html_themes_1 #+BEGIN_SRC css string theme_dark_1 = format(q"┃ h1 { color : #FFFFFF; background : #000000; } p.letter { color : #FFFFFF; background : #333333; } ┃"); string theme_light_1 = format(q"┃ h1 { color : #FFFFFF; background : #1A3A7A; } p.letter { color : #FFFFFF; background : #1A3A7A; } ┃"); #+END_SRC *** curated topics html head #+NAME: curated_topics_html_head_1 #+BEGIN_SRC d metadata_ ~= format(q"┃<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Curated metadata - Topics</title> #+END_SRC #+NAME: curated_topics_html_head_2 #+BEGIN_SRC d </head> #+END_SRC *** curated html head #+NAME: curated_html_head #+BEGIN_SRC d <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="dc.title" content= "metadata curate, Authors & Topics - information Structuring Universe, Structured information Serialised Units" /> <meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" /> <meta name="generator" content="spine" /> <link rel="generator" href="https://sisudoc.org" /> <link href="./css/curate.css" rel="stylesheet"> <style TYPE="text/css"> /* spine curate css default stylesheet */%s .norm, .bold { line-height : 150%%; margin-left : 1em; margin-right : 2em; margin-top : 10px; margin-bottom : 0px; text-indent : 0mm; } p, h0, h1, h2, h3, h4, h5, h6, h7 { display : block; font-family : verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; font-size : 100%%; font-weight : normal; line-height : 150%%; /* text-align : justify; */ margin-left : 1em; text-indent : 0mm; margin-top : 2px; margin-bottom : 2px; margin-right : 6px; text-align : left; } h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em #999999; } h1 { font-size : 120%%; font-weight : bold; color : #FFFFFF; background : #000088; margin-left : 0em; } p.work { font-size : 80%%; margin-left : 5em; margin-top : 0px; margin-bottom : 0px; margin-right : 6px; text-align : left; } p.author { font-size : 100%%; margin-left : 2em; margin-top : 0px; margin-bottom : 0px; margin-right : 6px; text-align : left; } p.publication { font-size : 80%%; margin-left : 4em; margin-top : 0px; margin-bottom : 0px; margin-right : 6px; text-align : left; } p.letter { font-weight : bold; font-size : 60%%; margin-left : 1em; margin-top : 0px; margin-bottom : 0px; margin-right : 6px; text-align : left; } p.lev0 { font-size : 120%%; margin-left : 1em; } p.lev1 { font-size : 110%%; margin-left : 2em; } p.lev2 { font-size : 100%%; margin-left : 3em; } p.lev3 { font-size : 90%%; margin-left : 4em; } p.lev4 { font-size : 80%%; margin-left : 5em; } p.lev5 { font-size : 80%%; margin-left : 6em; }%s /* flex */ .flex-menu-bar { display : -webkit-flex; display : flex; -webkit-flex-wrap : wrap; -webkit-align-items : center; align-items : center; width : 100%%; margin-left : 0%%; margin-right : 2%%; background-color : inherited; } .flex-menu-option { background-color : inherited; margin-right : 4px; } .flex-list { display : -webkit-flex; display : flex; -webkit-align-items : center; display : block; align-items : center; width : 100%%; background-color : inherited; } .flex-list-item { background-color : inherited; margin : 4px; } </style> <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> #+END_SRC *** curated html bottom #+NAME: curated_html_bottom #+BEGIN_SRC d ~= format(q"┃ <hr /> <a name="bottom" id="bottom"></a> <a name="down" id="down"></a> <a name="end" id="end"></a> <a name="finish" id="finish"></a> <a name="stop" id="stop"></a> <a name="credits"></a> </body> </html> ┃") ~ "\n"; #+END_SRC *** curated topics html head theme insert #+NAME: curated_topics_html_head_theme #+BEGIN_SRC d ┃", doc_matters.opt.action.css_theme_default ? theme_light_0 : theme_dark_0, doc_matters.opt.action.css_theme_default ? theme_light_1 : theme_dark_1, ) ~ "\n"; #+END_SRC *** search form #+NAME: curated_html_search #+BEGIN_SRC d @safe string inline_search_form(M)( M doc_matters, ) { string o; string _form; if (doc_matters.opt.action.html_link_search) { o = format(q"┃ <div class="flex-menu-option"> <!-- SiSU Spine Search --> <form action="%s" target="_top" method="POST" accept-charset="UTF-8" id="search"> <font size="2"> <input type="text" name="sf" size="24" maxlength="255">%s <input type="hidden" name="sml" value="1000"> <input type="hidden" name="ec" value="on"> <input type="hidden" name="url" value="on"> <button type="submit" form="search" name="fn" value="%s">doc</button> <button type="submit" form="search">※ db</button> </font></form> <!-- SiSU Spine Search --> </div>┃", doc_matters.conf_make_meta.conf.w_srv_cgi_action, (doc_matters.conf_make_meta.conf.w_srv_db_sqlite_filename.empty) ? "" : "\n <input type=\"hidden\" name=\"db\" value=\"" ~ doc_matters.conf_make_meta.conf.w_srv_db_sqlite_filename ~ "\">", doc_matters.src.filename_base, ); } else { o = ""; } return o; } #+END_SRC * document header including copyright & license #+NAME: doc_header_including_copyright_and_license #+BEGIN_SRC txt /+ - Name: Spine, Doc Reform [a part of] - Description: documents, structuring, processing, publishing, search - static content generator - Author: Ralph Amissah [ralph.amissah@gmail.com] - Copyright: (C) 2015 - 2023 Ralph Amissah, All Rights Reserved. - License: AGPL 3 or later: Spine (SiSU), a framework for document structuring, publishing and search Copyright (C) Ralph Amissah This program is free software: you can redistribute it and/or modify it under the terms of the GNU AFERO General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see [https://www.gnu.org/licenses/]. If you have Internet connection, the latest version of the AGPL should be available at these locations: [https://www.fsf.org/licensing/licenses/agpl.html] [https://www.gnu.org/licenses/agpl.html] - Spine (by Doc Reform, related to SiSU) uses standard: - docReform markup syntax - standard SiSU markup syntax with modified headers and minor modifications - docReform object numbering - standard SiSU object citation numbering & system - Homepages: [https://www.doc_reform.org] [https://www.sisudoc.org] - Git [https://git.sisudoc.org/projects/?p=software/spine.git;a=summary] +/ #+END_SRC * __END__