Toggle Code rows ⇄ Ordered with inline `<code>` format

This script is probably a bit specialised, but when toggling Code type rows to Ordered, I often want to retain their <code> appearance, rather than defaulting back to the standard font.

This script toggles selected rows in Bike, alternating its output message between:

  1. N row(s) toggled to code.
  2. N row(s) toggled to ordered, (with inline <code> formatting).

To test in Script Editor, set the language selector at top left to JavaScript
(rather than AppleScript)

See: Using Scripts | Bike


Expand disclosure triangle to view JS source
(() => {
    "use strict";

    // Toggle Selected Rows:
    // "Code" ⇄ "Ordered" with inline Code formatting

    // Rob Trew @2024
    // Ver 0.1

    // ---------------------- MAIN -----------------------
    // main :: IO ()
    const main = () => {
        const doc = Application("Bike").documents.at(0);

        return doc.exists()
            ? toggleCodeOrdered(
                doc.rows.where({selected: true})
            )
            : "No document open in Bike.";
    };

    // ---------------------- BIKE -----------------------

    // toggleCodeOrdered :: Bike Rows Specifier -> IO String
    const toggleCodeOrdered = rows => {
        // "Code" row type ⇄ "Ordered" with inline <code>
        // Note that the type of rows is NOT a JS Array.
        const nRows = rows.length;

        return 0 < nRows
            ? (() => {
                const
                    wasCode = "code" === rows.at(0).type(),
                    newType = wasCode
                        ? "ordered"
                        : "code";

                rows().forEach(x => {
                    const runs = x.textContent.attributeRuns;

                    // EFFECTS
                    // Row type
                    x.type = newType;

                    // Inline format
                    enumFromTo(0)(runs.length - 1)
                    .forEach(
                        i => runs.at(i).code = wasCode
                    );
                });

                return [
                    `${plural(nRows)("row")} toggled to '${newType}'`,
                    wasCode
                        ? ",\n(with inline <code> formatting)."
                        : "."
                ]
                .join("");
            })()
            : "No rows selected in Bike.";
    };


    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = m =>
        // Enumeration of the integers from m to n.
        n => Array.from(
            {length: 1 + n - m},
            (_, i) => m + i
        );


    // plural :: Int -> String -> String
    const plural = n =>
        // Singular or plural EN inflection
        // of a given word, preceded by digits.
        k => 1 === n
            ? `${n} ${k}`
            : `${n} ${k}s`;

    return main();
})();

and, of course, we can generalise this to toggle Bike code rows
to other row types, preserving their <code> formatted appearance.

Edit the value of altType, near the top of the generalised script below

const altType = "unordered";

To the name of some other Bike row type drawn from:

{body, heading, quote, note, task, ordered, unordered}

(i.e. any alternative Bike row type other than "hr" – horizontal row)

Expand disclosure triangle to view JS source
(() => {
    "use strict";

    // Toggle Selected Rows:
    // "code" ⇄ (alt type) with inline <code> formatting

    // Where the (alt type) is drawn from:
    // { body, heading, quote, note, task,
    //  ordered, unordered }
    // (i.e. the other Bike row types)

    // Rob Trew @2024
    // Ver 0.2b

    // --------------------- OPTION ----------------------
    const altType = "unordered";

    // ---------------------- MAIN -----------------------
    // main :: IO ()
    const main = () => {
        const doc = Application("Bike").documents.at(0);

        return doc.exists()
            ? toggleCodeRows(altType)(
                doc.rows.where({selected: true})
            )
            : "No document open in Bike.";
    };

    // ---------------------- BIKE -----------------------

    // toggleCodeRows :: String ->
    // Bike Rows Specifier -> IO String
    const toggleCodeRows = rowType =>
        // "Code" row type ⇄ rowType with inline <code>
        // Note that the type of rows is NOT a JS Array.
        // rowType ∈ {body, heading, quote, note,
        //  task, ordered, unordered} (Bike row types)
        rows => {
            const nRows = rows.length;

            return 0 < nRows
                ? (() => {
                    const
                        wasCode = "code" === rows.at(0).type(),
                        newType = wasCode
                            ? rowType
                            : "code";

                    rows().forEach(x => {
                        const runs = x.textContent.attributeRuns;

                        // EFFECTS
                        // Row type
                        x.type = newType;

                        // Inline format
                        enumFromTo(0)(runs.length - 1)
                        .forEach(
                            i => runs.at(i).code = wasCode
                        );
                    });

                    return [
                        `${plural(nRows)("row")} toggled to '${newType}'`,
                        wasCode
                            ? ",\n(with inline <code> formatting)."
                            : "."
                    ]
                    .join("");
                })()
                : "No rows selected in Bike.";
        };


    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = m =>
        // Enumeration of the integers from m to n.
        n => Array.from(
            {length: 1 + n - m},
            (_, i) => m + i
        );


    // plural :: Int -> String -> String
    const plural = n =>
        // Singular or plural EN inflection
        // of a given word, preceded by digits.
        k => 1 === n
            ? `${n} ${k}`
            : `${n} ${k}s`;

    return main();
})();



Three sample Keyboard Maestro macros in which the alternative row type is parameterised by a Keyboard Maestro variable. (Here ∈ {"ordered", "unordered", "task"})

rowTypeTogglePreservingCodeFormat.kmmacros.zip (15.0 KB)

1 Like