Skip to content

Instantly share code, notes, and snippets.

@bmccormack
Created August 11, 2025 18:22
Show Gist options
  • Save bmccormack/9a728eac3577ceadf44395ed1152181e to your computer and use it in GitHub Desktop.
Save bmccormack/9a728eac3577ceadf44395ed1152181e to your computer and use it in GitHub Desktop.
Postman Markdown Visualization Script

When using Postman to experiment with an API, you might receive a response where some of the data is formatted as markdown.

Before

CleanShot 2025-08-11 at 14 21 28

After

CleanShot 2025-08-11 at 14 21 56

Set up

You can add this to the "Scripts" section of the API definition as a "Post-response" script. It will then generate an easy-to-ready visualization of the data. There's some configuration required.

  1. Within your Postman API object, click the Scripts tab at the top.
  2. Click Post-response on the left.
  3. Paste in the contents of post-response.js.
  4. Find the line that says var summaryHtml = simpleMarkdown(res.summary); and replace res.summary with the object in your JSON response that includes markdown-formatted text.
CleanShot 2025-08-11 at 14 19 55
var template = `
<style type="text/css">
/* --- Basic Markdown CSS Style --- */
/* General Body & Layout */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.7;
font-size: 17px;
color: #333;
background-color: #fdfdfd;
margin: 0;
padding: 2rem;
}
/* Constrain content width for better readability */
body > *:not(h1, h2, h3, h4, h5, h6) {
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
/* --- Typography --- */
/* Headings */
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
line-height: 1.2;
margin-top: 2em;
margin-bottom: 0.8em;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
h1 { font-size: 2.2em; }
h2 { font-size: 1.8em; border-bottom: 1px solid #eee; padding-bottom: 0.3em; }
h3 { font-size: 1.5em; }
h4 { font-size: 1.2em; }
h5 { font-size: 1.0em; }
h6 { font-size: 0.9em; color: #777; }
/* Paragraphs */
p {
margin-bottom: 1.2em;
}
/* Links */
a {
color: #007bff;
text-decoration: none;
transition: color 0.2s ease-in-out;
}
a:hover {
color: #0056b3;
text-decoration: underline;
}
/* --- Block Elements --- */
/* Blockquotes */
blockquote {
margin: 1.5em 0;
padding: 0.5em 1.5em;
color: #555;
background-color: #f9f9f9;
border-left: 5px solid #ccc;
}
blockquote p {
margin-bottom: 0;
}
/* Lists */
ul, ol {
padding-left: 2em;
margin-bottom: 1.2em;
}
li {
margin-bottom: 0.5em;
}
/* Code Blocks */
pre {
background-color: #f3f3f3;
border: 1px solid #ddd;
border-radius: 5px;
padding: 1em;
overflow-x: auto; /* Handle long lines of code */
font-size: 0.9em;
line-height: 1.4;
max-width: 800px;
margin: 1.5em auto;
}
/* Inline Code */
code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
background-color: #f3f3f3;
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 0.9em;
}
/* Code inside a pre block should not have extra styling */
pre code {
background-color: transparent;
padding: 0;
border-radius: 0;
font-size: inherit;
}
/* --- Other Elements --- */
/* Horizontal Rule */
hr {
border: 0;
height: 1px;
background-color: #ddd;
margin: 3em auto;
max-width: 800px;
}
/* Images */
img {
max-width: 100%;
height: auto;
display: block;
margin: 1.5em auto;
border-radius: 5px;
}
/* Tables */
table {
width: 100%;
border-collapse: collapse;
margin: 1.5em 0;
display: block;
overflow-x: auto;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
th, td {
border: 1px solid #ddd;
padding: 0.8em;
text-align: left;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
tbody tr:nth-child(odd) {
background-color: #f9f9f9;
}
</style>
<div class="summary-text">
{{{response.summary}}}
</div>
`;
//=== simple markdown parser (updated on 2021/10/11, v0.63)
function simpleMarkdown(mdText) {
// function for REGEXP to show html tag. ie. <TAG> => &lt;TAG*gt;
var formatTag = function (html) { return html.replace(/</g,'&lt;').replace(/\>/g,'&gt;'); }
// format code-block, highlight remarks/keyword
var formatCode = function(m,p1,p2){
p2 = p2.replace(/</g,'&lt;').replace(/\>/g,'&gt;').replace(/\/\/(.*)$/gm,'<rem>//$1</rem>')
p2 = p2.replace(/(function |return |var |let |const |else |if |for |while |continue |break |case |switch )/gim,'<b>$1</b>')
return '<pre title="' + p1 + '"><code>' + p2 + '</code></pre>'
}
// function to convert mdString into HTML string
var formatMD = function( mdstr ) {
return mdstr.replace(/^##### (.*?)\s*#*$/gm, '<h5>$1</h5>')
.replace(/^#### (.*?)\s*#*$/gm, '<h4>$1</h4>')
.replace(/^### (.*?)\s*#*$/gm, '<h3>$1</h3>')
.replace(/^## (.*?)\s*#*$/gm, '<h2>$1</h2>')
.replace(/^# (.*?)\s*#*$/gm, '<h1>$1</h1>')
.replace(/^<h(\d)\>(.*?)\s*{(.*)}\s*<\/h\d\>$/gm, '<h$1 id="$3">$2</h$1>')
.replace(/^-{3,}|^\_{3,}|^\*{3,}/gm, '<hr/>')
.replace(/``(.*?)``/gm, function(m,p){ return '<code>' + formatTag(p).replace(/`/g,'&#96;') + '</code>'} )
.replace(/`(.*?)`/gm, '<code>$1</code>' )
.replace(/^\>> (.*$)/gm, '<blockquote><blockquote>$1</blockquote></blockquote>')
.replace(/^\> (.*$)/gm, '<blockquote>$1</blockquote>')
.replace(/<\/blockquote\>\n<blockquote\>/g, '\n<br>' )
.replace(/<\/blockquote\>\n<br\><blockquote\>/g, '\n<br>' )
.replace(/!\[(.*?)\]\((.*?) "(.*?)"\)/gm, '<img alt="$1" src="$2" $3 />')
.replace(/!\[(.*?)\]\((.*?)\)/gm, '<img alt="$1" src="$2" />')
.replace(/\[(.*?)\]\((.*?) "new"\)/gm, '<a href="$2" target=_new>$1</a>')
.replace(/\[(.*?)\]\((.*?) "(.*?)"\)/gm, '<a href="$2" title="$3">$1</a>')
.replace(/<http(.*?)\>/gm, '<a href="http$1">http$1</a>')
.replace(/\[(.*?)\]\(\)/gm, '<a href="$1">$1</a>')
.replace(/\[(.*?)\]\((.*?)\)/gm, '<a href="$2">$1</a>')
.replace(/^[\*|+|-][ |.](.*)/gm, '<ul><li>$1</li></ul>' ).replace(/<\/ul\>\n<ul\>/g, '\n' )
.replace(/^\d[ |.](.*)/gm, '<ol><li>$1</li></ol>' ).replace(/<\/ol\>\n<ol\>/g, '\n' )
.replace(/\*\*\*(.*)\*\*\*/gm, '<b><em>$1</em></b>')
.replace(/\*\*(.*)\*\*/gm, '<b>$1</b>')
.replace(/\*([\w \d]*)\*/gm, '<em>$1</em>')
.replace(/___(.*)___/gm, '<b><em>$1</em></b>')
.replace(/__(.*)__/gm, '<u>$1</u>')
.replace(/_([\w \d]*)_/gm, '<em>$1</em>')
.replace(/~~(.*)~~/gm, '<del>$1</del>')
.replace(/\^\^(.*)\^\^/gm, '<ins>$1</ins>')
.replace(/ \n/g, '\n<br/>')
.replace(/\n\s*\n/g, '\n<p>\n')
.replace(/^ {4,10}(.*)/gm, function(m,p){ return '<pre><code>' + formatTag(p) + '</code></pre>'} )
.replace(/^\t(.*)/gm, function(m,p){ return '<pre><code>' + formatTag(p) + '</code></pre>'} )
.replace(/<\/code\><\/pre\>\n<pre\><code\>/g, '\n' )
.replace(/\\([`_~\*\+\-\.\^\\\<\>\(\)\[\]])/gm, '$1' )
}
// first, handle syntax for code-block
var pos1=0, pos2=0, mdHTML = ''
mdText = mdText.replace(/\r\n/g, '\n').replace(/\n~~~/g,'\n```')
mdText = mdText.replace(/\n``` *(.*?)\n([\s\S]*?)\n``` *\n/g, formatCode )
// split by "<code>", skip for code-block and process normal text
while ( (pos1 = mdText.indexOf('<code>')) >= 0 ) {
pos2 = mdText.indexOf('</code>', pos1 )
mdHTML += formatMD( mdText.substr(0,pos1) ) + mdText.substr(pos1+6, (pos2>0? pos2-pos1-6 : mdtext.length) )
mdText = mdText.substr( pos2 + 7 )
}
return mdHTML + formatMD( mdText )
}
function constructVisualizerPayload() {
var res = pm.response.json();
var summaryHtml = simpleMarkdown(res.summary);
return {response: {summary: summaryHtml}};
}
pm.visualizer.set(template, constructVisualizerPayload());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment