Action

Advanced Print/PDF export

Posted by RoyRogers, Last update almost 5 years ago

Advanced Print / PDF export.

Prints current draft or directly from clipboard:

  • Uses predefined css-drafts with tag: ‘css-print’
  • Select to preserve line breaks, add TOC, or show preview.
  • Settings are saved between runs.
  • The actual printing is in a separate “Print” action step.
  • Style-drafts are plain css, so easy to apply any css.
  • PDFs can be made in the iOS print preview (not Drafts preview) by two finger expand gesture and then tapping share button.

Steps

  • script

    // Advanced Print
    // RV 2020-03-26 at 21:01
    
    // Chose predefined css drafts with tag: 'css-print'
    // Print current draft or directly from clipboard.
    // Select to preserve ln, add toc, and show preview
    // Settings are saved between runs.
    // The actual printing is in the following action step.
    // Style drafts are plain css, so easy to apply any css.
    
    'use strict';
    let tocHead = '### Table of Contents'
    let path = '/print-settings.json'
    
    function main() {
      // prompt to select
      let st = getSettings();
      let p = Prompt.create();
      p.title = "Print Menu";
      // p.message = "Select Print Style:";
      p.addSelect('source', "Select Source:", ['Current Draft', 'Text in Clipboard'], [st.source], false);
      p.addSwitch("ln", "Keep Line Breaks", st.ln);
      p.addSwitch("prev", "Show Preview", st.prev);
      p.addSwitch("toc", "Make TOC", st.toc);
      
      let cssList = getCSS();
      // p.addButton('Default Style', -1);
      let i = 0
      for (let cssObj of cssList) {
        p.addButton(cssObj.title, i);
        i++;
      }
      
      if (!p.show()) {
        context.cancel('canceled by user');
        return false;
      }
      
      // get the selected css draft
      let selIndex = parseInt(p.buttonPressed);
      let cssObj = cssList[selIndex];
      let css = cssObj.css;
      st.toc = p.fieldValues['toc'];
      st.prev = p.fieldValues['prev'];
      st.ln = p.fieldValues['ln'];
      let doc = '';
      
      // let sel = p.fieldValues['source'][0];
      st.source = p.fieldValues['source'][0];
      switch (st.source) {
        case 'Current Draft':
          doc = draft.content;
          break;
        case 'Text in Clipboard':
          doc = app.getClipboard();
          break;
        default:
          app.displayErrorMessage('switch/case not implemented!');
          return;
      }
      makeHTML(doc, css, st);
      // print is done in next action step, using [[html]] template tag.
    }
    
    function getSettings() {
      let fmCloud = FileManager.createCloud();
      let settings = fmCloud.readString(path);
      if (!settings) { 
        // No file found, use default;
        var obj = {'source': 'Current Draft', 'ln': true, 'toc': false, 'prev': true}
      } else {
        var obj = JSON.parse(settings)
      }
    
      return obj;
    }
    
    function saveSettings(obj) {
      let fmCloud = FileManager.createCloud();
      let success = fmCloud.write(path, JSON.stringify(obj));
    }
    
    function makeHTML(doc, css, st) {
      let mmd = MultiMarkdown.create();
      mmd.format = "html";
      
      if (st.toc) {
        doc = doc.replace(/\n/, '\n\n' + tocHead + '\n{{TOC}}')
      }
      
      if (st.ln) {
        // add 2 spaces to end of line 
        doc = doc.replace(/(\S+?) *$/gm, '$1  ');
      }
    
      let body = mmd.render(doc);
      // css = '';
      let html = `<html>
      <style>
      ${css}
      </style>
      <body>
      ${body}
      </div>
      </body>
      </html>
      `
      
      if (st.prev) {
        let preview = HTMLPreview.create();
        if (!preview.show(darklight(html))) {
          context.cancel('canceled by user');
          return;
        }
      }
      saveSettings(st);
      draft.setTemplateTag("html", html);
    }
    
    function getCSS() {
      // get list of drafts in all
      let drafts = Draft.query("", "all", ['css-print'], [''], 'name');
      
      // check if found any valid ccs
      if (drafts.length == 0) {
        alert(`No Style Sheet found,
        only Default style available.
        
        To make other styles available,
        create a draft with css content
        and assign the tag "css-print\".`);
      }
      
      let cssList = [{'title': 'Default Monospace Style', 'i': 0, 'css': defaultCSS}];
      // p.addButton('Default Style', -1);
      let i = 1
      for (let d of drafts) {
        let title = d.title.replace(/\/\* *(.+?)(.css)? *\*\//, '$1');
        let css = d.content;
        cssList.push({'title': title, 'i': i, 'css': css});
        i++;
      }
      return cssList;
    }
    
    let defaultCSS = `/* Default CSS monospace style */
    body {
      font-family: Menlo, monospace;
      font-size: 100%;
    }`;
    
    function darklight(html) {
      // create theme sensitive css for preview
      
      if (app.themeMode == 'dark') {
        var css = "\nbody { background: #222; color: #ddd; }\n";
      } else {
        var css = "\nbody { background: #fff; color: #444; }\n";
      }
      return html.replace(/<\/style>/, css + '</style>');
    }
    
    main();
    
    
  • print

    template
    [[html]]
    format
    html

Options

  • After Success Default
    Notification Error
    Log Level Info
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.