Reading named styles off of a cell using JXA


#1

I’m working on a script to convert an OmniOutliner outline of an academic paper to markdown. The plan is to use named styles to indicate cells that need special markdown tags, such as headings (#, ##, etc.) and quotes (>). But I haven’t yet figured out how to access the named styles applied to cells in javascript so that I can include a suitable switch statement such as:

switch(style) {
    case "Heading 1": 
        paperText += "# ";
        break;
    case "Quote": 
        paperText += "> ";
        break;
}

Does anyone know how to do this? Thanks!

Best,
David


#2

@dmgrant

Just learning JXA, but here is an example of how I got the name of named style of the 8th row (the one colored red) of a document based on the Classic Theme template. --> “Red”.

The way I understand it, a row’s style can contain one or more named styles. This retrieves the name of the first named style.

SG

oo = Application('OmniOutliner');
var frontDoc = oo.documents[0];
var theRow = frontDoc.rows[7];

theRow.style.namedStyles[0].name();

#3

You are awesome, thank you so much. It worked!

Here’s the completed code that assembles a UTF8-encoded string with the text of the entire OmniOutliner document, minus notes/any additional columns. (You have to convert to UTF8 first if you want to pass the string to pandoc.) Now I just need to figure out how to automatically parse italics/bold into the relevant tags…

var OmniOutliner = Application('OmniOutliner');
var doc = OmniOutliner.documents[0];
var paperText = "";

// Loop through rows and append their text to paperText, adding markdown tags for rows based on their named style

doc.rows().forEach(function(theRow) {
    // Check if this row has named styles
	if (Object.keys(theRow.style.namedStyles).length > 0) {
            // Just looks at the first namedStyle it finds; won't behave as expected if you apply more than one of these named styles to a row.
		switch(theRow.style.namedStyles[0].name()) {
			case "Heading 1":
				paperText += "# ";
				break;
			case "Heading 2":
				paperText += "## ";
				break;
			case "Heading 3":
				paperText += "### ";
				break;
			case "Blockquote": // Custom named style
				paperText += "> ";
				break;
			case "Ordered List": // Custom named style
				paperText += "1. ";
				break;
			case "Unordered List": // Custom named style
				paperText += "* ";
				break;
		}	
	}
	paperText += theRow.cells[1].richText();
	paperText += "\r\r";
});

// Convert the text of the paper to UTF8 encoding so that e.g. pandoc can read it

paperText = $.NSString.alloc.initWithUTF8String(paperText);

#4

Anyone updated this to the latest OmniAutomation functionality?

I’d like to get the style name, but this is returning “undefined”

rootItem.descendants.forEach(function(item) {
    style = item.style.name

#5

I worked it out:

rootItem.descendants.forEach(function(item) {
    if (typeof (item.style.namedStyles[0]) !== "undefined") {
        style = item.style  // returns object of type Style
        firstStyle = style.namedStyles[0]  // first named style
        styleName = firstStyle.name
        // code block
    }

Caveat: there are potentially several namedStyles. For my use, I just want the first one.