Quick preview in Marked.app

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();
})();
2 Likes