A script which opens a preview of the active TaskPaper document in Brett Terpstra’s Marked.app.
(by opening a temporary BML - (html subset for outlines) serialization of the TaskPaper file)
JavaScript source below.
See Using Scripts in TaskPaper 3
Keyboard Maestro macro:
Show or print as rendered BML in Marked.kmmacros.zip (11.3 KB)
JS Source
(() => {
'use strict';
// main :: IO ()
const main = () =>
either(
alert('Problem')
)(
append('Displayed in ')
)(bindLR(
(ds => ds.length > 0 ? (
Right(ds.at(0))
) : Left('No TaskPaper documents open'))(
Application('TaskPaper').documents
)
)(d => bindLR(
d.evaluate({
script: tp3Context.toString()
})
)(bml => {
const
html = unlines(
lines(bml).slice(1)
),
fp = getTemporaryDirectory() + (
'tp3.bml'
),
marked = Application(
'com.brettterpstra.marked2'
);
marked.activate();
return (
writeFile(fp)(html),
marked.open(fp),
Right(
marked.name()
)
);
})));
// ----------------- TASKPAPER CONTEXT -----------------
const tp3Context = (editor, options) => {
const tp3Main = () =>
Right(
editor.outline.serialize({
type: ItemSerializer.BMLType
})
);
// -------------------- GENERIC --------------------
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
return tp3Main();
};
// ------------------------ JXA ------------------------
// alert :: String => String -> IO String
const alert = title => s => {
const
sa = Object.assign(Application(
'System Events'
), {
includeStandardAdditions: true
});
return (
sa.activate(),
sa.displayDialog(s, {
withTitle: title,
buttons: ['OK'],
defaultButton: 'OK',
withIcon: sa.pathToResource(
'TaskPaper.icns', {
inBundle: 'Applications/TaskPaper.app'
})
}),
s
);
};
// ----------------- GENERIC FUNCTIONS -----------------
// https://github.com/RobTrew/prelude-jxa
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// append (++) :: [a] -> [a] -> [a]
const append = xs =>
// A list defined by the
// concatenation of two others.
ys => xs.concat(ys);
// bindLR (>>=) :: Either a ->
// (a -> Either b) -> Either b
const bindLR = m =>
mf => undefined !== m.Left ? (
m
) : mf(m.Right);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => 'Either' === e.type ? (
undefined !== e.Left ? (
fl(e.Left)
) : fr(e.Right)
) : undefined;
// getTemporaryDirectory :: IO FilePath
const getTemporaryDirectory = () =>
ObjC.unwrap($.NSTemporaryDirectory());
// lines :: String -> [String]
const lines = s =>
// A list of strings derived from a single
// newline-delimited string.
0 < s.length ? (
s.split(/[\r\n]/)
) : [];
// unlines :: [String] -> String
const unlines = xs =>
// A single string formed by the intercalation
// of a list of strings with the newline character.
xs.join('\n');
// writeFile :: FilePath -> String -> IO ()
const writeFile = fp => s =>
$.NSString.alloc.initWithUTF8String(s)
.writeToFileAtomicallyEncodingError(
$(fp)
.stringByStandardizingPath, false,
$.NSUTF8StringEncoding, null
);
// MAIN ---
return main();
})();