Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[idea] Put data for pdf header/footer directly into the <script> section of markdown to get rid of changing header/footer settings each time #396

Open
pediRAM opened this issue Jan 25, 2025 · 0 comments

Comments

@pediRAM
Copy link

pediRAM commented Jan 25, 2025

First of all I want to thank all contributers for this amazing plug-in.

My Problem

I work on many different manuals, books and documentations etc. at the same time and I use the same header-template for nearly all markdown files but with different data like title or version for current document. So the reader can see the title or (customized) pdf-creation-date like "2025-01" on every page of PDF, like this:

Image

I had to open the Plug-in settings and change the "Header Template" everytime I opened another markdown file (with completely other topic) and often I forgot to replace the title string in the header template (plug-in settings)... This cost me a lot of attention and time.

My Solution

Why not putting meta-data about the markdown file used for header of PDF pages directly into the markdown file itself?
This way each markdown file contains its own data for the header and I don't have to change the header for PDF in plug-in-settings no more!

The value of Markdown PDF Plug-in-Setting Header Template:

<div style="font-size: 9px; margin-left: 1cm; display: display;"> <span>%pdfPageHeaderDate% %pdfPageHeaderTitle%</span></div> <div style="font-size: 9px; margin-left: auto; margin-right: 1cm;  display: display;">%pdfPageHeaderCopyright%</div>

Step 1: Add Data to Script-Section of Markdown file

I put the custom values for current markdown file like title, date, author, copyright etc. directly into the markdown as variable values in a <script> section like this:

<script>
var pdfPageHeaderTitle = "ABC todo Liste";
var pdfPageHeaderVersion = "1.2.3";
var pdfPageHeaderDate = "%yyyy%-%mm%-%dd%";
var pdfPageHeaderAuthor = "John Doe";
var pdfPageHeaderCopyright = "Copyright ©%yyyy% by %pdfPageHeaderAuthor%";
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({ tex2jax: {inlineMath: [['$', '$']]}, messageStyle: "none" });
</script>

<!-- Markdown content after this line -->
# To do
> Just some text...

Step 2: Add Variables and Function to extract them into extension.js

'use strict';
var vscode = require('vscode');
var path = require('path');
var fs = require('fs');
var url = require('url');
var os = require('os');
var INSTALL_CHECK = false;
/****************************************** INSERTED CODE FOR PDF-PAGES-HEADER *****************************/
var customPageHeaderVariables = {
  pdfPageHeaderTitle : "?pdfPageHeaderTitle?",
  pdfPageHeaderVersion : "?pdfPageHeaderVersion?",
  pdfPageHeaderCopyright : "?pdfPageHeaderCopyright?",
  pdfPageHeaderDate : "?pdfPageHeaderDate?"
};

function extractVariablesFromMarkdown(markdownContent) {
  const variables = {};
  const scriptRegex = /<script>([\s\S]*?)<\/script>/gi; 
  let match;

  while ((match = scriptRegex.exec(markdownContent)) !== null) {
      const scriptContent = match[1];
      scriptContent.split(';').forEach(line => {
          const [key, value] = line.split('=').map(part => part.trim());
          if (key && value) {
              const cleanKey = key.replace(/var\s+/, '');
              variables[cleanKey] = value.replace(/^["']|["']$/g, ''); 
          }
      });
  }
  return variables;
}
/************************************************************************************************/

Step 3: Modify Function "async function markdownPdf(option_type)"

Search for the above function signature (in extensions.js) and add following line:

          var content = convertMarkdownToHtml(mdfilename, type, text);
         /***************************** ADD THIS LINE *****************************/
          customPageHeaderVariables = extractVariablesFromMarkdown(content);
         /****************************************************************************/
          var html = makeHtml(content, uri);
          await exportPdf(html, filename, type, uri);
         ...

Step 3: Modify Method "function transformTemplate(templateText)" and add new Function "function generateHeaderTemplate(templateText)"

/**
 * Transform the text of the header or footer template, replacing the following supported placeholders:
 *
 * - `%%ISO-DATETIME%%` – For an ISO-based date and time format: `YYYY-MM-DD hh:mm:ss`
 * - `%%ISO-DATE%%` – For an ISO-based date format: `YYYY-MM-DD`
 * - `%%ISO-TIME%%` – For an ISO-based time format: `hh:mm:ss`
 */
function transformTemplate(templateText) {
  // First replace pdf-page-header-parameters by values found from <script> section in markdown,
  //  so we can use date/time parameter keys in pdf-page-header-parameter values (from <script> section).
  templateText = generateHeaderTemplate(templateText);
  let year = new Date().getFullYear().toString();
  let month = new Date().getMonth() + 1;
  let mm = month < 10 ? "0" + month.toString() : month.toString();
  let day = new Date().getDate();
  let dd = day < 10 ? "0" + day : day.toString();

    templateText = templateText
    .replace(/%ISO-DATETIME%/g, new Date().toISOString().substr(0, 19).replace('T', ' ') || '')
    .replace(/%ISO-DATE%/g, new Date().toISOString().substr(0, 10) || '')
    .replace(/%ISO-TIME%/g, new Date().toISOString().substr(11, 8) || '')
    .replace(/%yyyy%/g, year || '')
    .replace(/%mm%/g, mm || '')
    .replace(/%month%/g, month || '')
    .replace(/%day%/g, day || '')
    .replace(/%dd%/g, dd || '')
    .replace(/%yyyy-mm%/g, new Date().getFullYear().toString() + "-" + mm || '');
  return templateText;
}

/********************* NEW FUNCTION *****************/
function generateHeaderTemplate(templateText) {
  let updatedTemplate = templateText;
  updatedTemplate = updatedTemplate
      .replace(/%pdfPageHeaderTitle%/g, customPageHeaderVariables.pdfPageHeaderTitle || '')
      .replace(/%pdfPageHeaderVersion%/g, customPageHeaderVariables.pdfPageHeaderVersion || '')
      .replace(/%pdfPageHeaderDate%/g, customPageHeaderVariables.pdfPageHeaderDate || '')
      .replace(/%pdfPageHeaderCopyright%/g, customPageHeaderVariables.pdfPageHeaderCopyright || '')
      .replace(/%pdfPageHeaderAuthor%/g, customPageHeaderVariables.pdfPageHeaderAuthor || '');
  return updatedTemplate;
}
/***************************************************/
...

Step 4

Restart VS Code!

Last Step

Open your markdown file (containing the <script> section with pdf-header values as variables (if not already done after restarting VS Code) and press CTRL + S keys to save, if you have enabled auto-convert to PDF, else do it by calling the command.

Image

From now on, you don't need to touch the Header Template in the Markdown PDF Plug-in Settings anymore :-)

As you may noticed, I also changed the code to for replacing %%%ISO-DATE%%% etc. in the way of calling replace method (by regular expression), reduced the usage of % character from triple to only one, and also added following keys for more flexibility:

  • %yyyy% for current year, like: 2025
  • %month% for current month, like: 1 (for january)
  • %mm% for current month, like: 01 (for january)
  • %day% for current day, like: 1, ..., 31
  • %dd% for current day, like: 01, ..., 31
  • %yyyy-mm% for current year and mnoth, like: 2025-01

You can also use the date-keys (like %ISO-DATE% or %yyyy% etc.) in the pdf-header-variable-values in the <script> section.

You also can put the author key %pdfPageHeaderAuthor% into the value of pdfPageHeaderCopyright.

I hope this can help some of you with the same problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant