Skip to content

Instantly share code, notes, and snippets.

@thomaswilburn
Last active April 10, 2019 02:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomaswilburn/5bdda5ec3889157a50dfad01255ae1ac to your computer and use it in GitHub Desktop.
Save thomaswilburn/5bdda5ec3889157a50dfad01255ae1ac to your computer and use it in GitHub Desktop.
CommonMark-ish rendering into Google Docs
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
function renderMD(body, lines) {
if (typeof lines == "string") {
lines = lines.split("\n");
}
lines.forEach(function(line) {
if (line.match(/^[-=+]+$/)) {
return body.appendHorizontalRule();
}
var extractHeading = line.match(/^(#+)?\s*(.*)/);
var headerCode = extractHeading[1];
var rest = extractHeading[2];
var pStyle = DocumentApp.ParagraphHeading.NORMAL;
if (headerCode) {
pStyle = DocumentApp.ParagraphHeading["HEADING" + headerCode.length];
}
// parse into tokens
var buffer = "";
var parsed = [];
var escaping = false;
for (var i = 0; i < rest.length; i++) {
var char = rest[i];
switch (char) {
case "*":
case "_":
if (buffer) parsed.push({ text: buffer });
buffer = "";
parsed.push({ mark: char });
break;
case "\\":
buffer += rest[++i];
break;
case "[":
var remainder = rest.slice(i + 1);
var match = remainder.match(/^([^\]]+)\]\(([^)]+)\)/);
if (match) {
var all = match[0];
var text = match[1];
var url = match[2];
if (buffer) parsed.push({ text: buffer });
buffer = "";
parsed.push({
type: "link",
text: text,
url: url
});
i += all.length;
break;
}
default:
buffer += char;
}
}
if (buffer) parsed.push({ text: buffer });
// take the parsed text and generate a paragraph
var textContent = parsed
.map(function(token) { return token.text })
.filter(function(d) { return d })
.join("");
var paragraph = body.appendParagraph(textContent);
paragraph.setHeading(pStyle);
var textObject = paragraph.editAsText();
var offset = 0;
var marks = {};
parsed.forEach(function(token) {
if (token.mark) {
if (token.mark in marks) {
var start = marks[token.mark];
var methods = {
"*": "setBold",
"_": "setItalic"
};
var setter = methods[token.mark];
textObject[setter](start, offset - 1, true);
delete marks[token.mark];
} else {
marks[token.mark] = offset;
}
}
if (token.url) {
textObject.setLinkUrl(offset, offset + token.text.length - 1, token.url);
}
if (token.text) {
offset += token.text.length;
}
});
});
}
function test() {
var src = [
"### headline 3",
"_italic [with link](http://google.com)_",
"---",
"text _italics_ [link](http://example.com) text *bold* text",
"some *bold* text",
"",
"nothing much"
];
body.clear();
renderMD(body, src);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment