Action

Generate Snippet to Clipboard

Posted by rupes, Last update 7 days ago

UPDATES

7 days ago

My first share, so wanted to refformat it and deselect ‘unlisted’ option

An action I added to the Snippets workspace.

The action does the following:
- It runs on the draft being viewed
- Prompts for FIELDs enclosed in <<>>, with optional default values <<FIELD(default_option)>>
- After entering value(s), they can be used in the draft using ‘$FIELD’
- The filled in draft is then copied to the clipboard, leaving the original untouched.

If the first line of the draft starts with “# ”, it is considered the draft’s title, so is not included in generated text.

If there are no fields in the draft, you are given the option to cancel processing or just copy draft, without a title, to the clipboard.

Steps

  • script

    // Script copies to clipboard only 
    //   WITH variable substitution for <field> and $field
    // 
    
    // Parse draft
    let lines = draft.content.split("\n");
    let hasTitle = lines[0].startsWith("# ");
    let bodyLines = hasTitle ? lines.slice(1) : lines;
    let body = bodyLines.join("\n");
    
    // Match <<field>> or <<field(default)>>
    let regex = /<<([a-zA-Z0-9_]+)(?:\(([^<>]*)\))?>>/g;
    let placeholders = new Map();
    let match;
    
    while ((match = regex.exec(body)) !== null) {
      let field = match[1];
      let def = match[2] || "";
      if (!placeholders.has(field)) {
        placeholders.set(field, { default: def });
      }
    }
    
    // Utility: convert field name to title-case with colon
    function toTitleCase(str) {
      return str
        .toLowerCase()
        .replace(/_/g, " ")
        .replace(/\b\w/g, c => c.toUpperCase())
        .trim() + ":";
    }
    
    // Evaluate default values that refer to other fields
    function evaluateDefault(def, values) {
      return def.replace(/<<([a-zA-Z0-9_]+)>>/g, (m, key) => values[key] || "");
    }
    
    // If no placeholders found
    if (placeholders.size === 0) {
      let confirm = Prompt.create();
      confirm.title = "No Fields Found";
      confirm.message = "No placeholders like <<field>> were found in the draft.\nCopy draft body to clipboard?";
      confirm.addButton("OK");
      confirm.addButton("Cancel");
    
      if (confirm.show() && confirm.buttonPressed === "OK") {
        app.setClipboard(body);
        alert("Copied draft body to clipboard.");
      }
    } else {
      let prompt = Prompt.create();
      prompt.title = "Fill Template Fields";
    
      for (let [field, { default: def }] of placeholders) {
        let label = toTitleCase(field);
        let defaultValue = evaluateDefault(def, {});
        prompt.addTextField(field, label, defaultValue);
      }
    
      prompt.addButton("OK");
    
      if (prompt.show()) {
        let values = prompt.fieldValues;
    
        // Fill in missing fields from evaluated defaults
        for (let [field, data] of placeholders) {
          if (!values[field]) {
            values[field] = evaluateDefault(data.default, values);
          }
        }
    
        // Replace <<field(...)>> and <field> and $field
        let output = body
          .replace(/<<([a-zA-Z0-9_]+)(?:\([^<>]*\))?>>/g, (m, key) => values[key] || "")
          .replace(/<([a-zA-Z0-9_]+)>/g, (m, key) => values[key] || "");
    
        app.setClipboard(output);
        alert("Processed draft copied to clipboard.");
      }
    }

Options

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