Skip to content

Instantly share code, notes, and snippets.

@david-crespo
Last active July 31, 2020 01:41
Show Gist options
  • Save david-crespo/b5227e8af18416835ef638f72500f664 to your computer and use it in GitHub Desktop.
Save david-crespo/b5227e8af18416835ef638f72500f664 to your computer and use it in GitHub Desktop.
Markdown to JIRA script

Markdown to JIRA script

CLI script to convert your Markdown notes to JIRA format.

This is adapted from the to_jira function here:

https://github.com/kylefarris/J2M/blob/89b878/index.js#L73

Usage

Copy md-to-jira.js to your system. Takes either a filename or stdin:

node md-to-jira.js <filename>

or

cat <filename> | node md-to-jira.js

It may be convenient to define an alias like this:

alias to-jira='node path/to/script/md-to-jira.js'
Copyright 2013 Fokke Zandbergen
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
const fs = require("fs");
const filename = process.argv[2];
const md = fs.readFileSync(filename || 0, "utf-8"); // read file or stdin
console.log(toJira(md));
function toJira(str) {
var map = {
//cite: '??',
del: "-",
ins: "+",
sup: "^",
sub: "~"
};
return (
str
// Bold, Italic, and Combined (bold+italic)
.replace(/([*_]+)(\S.*?)\1/g, function(match, wrapper, content) {
switch (wrapper.length) {
case 1:
return "_" + content + "_";
case 2:
return "*" + content + "*";
case 3:
return "_*" + content + "*_";
default:
return wrapper + content * wrapper;
}
})
// All Headers (# format)
.replace(/^([#]+)(.*?)$/gm, function(match, level, content) {
return "h" + level.length + "." + content;
})
// Headers (H1 and H2 underlines)
.replace(/^(.*?)\n([=-]+)$/gm, function(match, content, level) {
return "h" + (level[0] === "=" ? 1 : 2) + ". " + content;
})
// Ordered lists
.replace(/^([ \t]*)\d+\.\s+/gm, function(match, spaces) {
return Array(Math.floor(spaces.length / 2 + 1)).join("#") + "# ";
})
// Un-Ordered Lists
.replace(/^([ \t]*)\*\s+/gm, function(match, spaces) {
return Array(Math.floor(spaces.length / 2 + 1)).join("*") + "* ";
})
// Headers (h1 or h2) (lines "underlined" by ---- or =====)
// Citations, Inserts, Subscripts, Superscripts, and Strikethroughs
.replace(
new RegExp("<(" + Object.keys(map).join("|") + ")>(.*?)</\\1>", "g"),
function(match, from, content) {
var to = map[from];
return to + content + to;
}
)
// Other kind of strikethrough
.replace(/\s+~~(.*?)~~\s+/g, " -$1- ")
// Named/Un-Named Code Block
.replace(/`{3,}(\w+)?((?:\n|[^`])+)`{3,}/g, function(
match,
synt,
content
) {
var code = "{code";
if (synt) code += ":" + synt;
return code + "}" + content + "{code}";
})
// Inline-Preformatted Text
.replace(/`([^`]+)`/g, "{{$1}}")
// Named Link
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, "[$1|$2]")
// Un-Named Link
.replace(/<([^>]+)>/g, "[$1]")
// Single Paragraph Blockquote
.replace(/^>/gm, "bq.")
// tables
.replace(
/^\n((?:\|.*?)+\|)[ \t]*\n((?:\|\s*?\-{3,}\s*?)+\|)[ \t]*\n((?:(?:\|.*?)+\|[ \t]*\n)*)$/gm,
function(match, headerLine, separatorLine, rowstr) {
var headers = headerLine.match(/[^|]+(?=\|)/g);
var separators = separatorLine.match(/[^|]+(?=\|)/g);
if (headers.length !== separators.length) {
return match;
}
var rows = rowstr.split("\n");
if (rows.length === 1 + 1 && headers.length === 1) {
// panel
return (
"{panel:title=" +
headers[0].trim() +
"}\n" +
rowstr.replace(/^\|(.*)[ \t]*\|/, "$1").trim() +
"\n{panel}\n"
);
} else {
return "||" + headers.join("||") + "||\n" + rowstr;
}
}
)
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment