×

Plug-In: Paragraph Attributes Apple Vision Pro

A plug-in for setting and restoring the paragraph attributes of the note of the selected project or task.

(NOTE: This plug-in requires OmniFocus 4.x)

Paragraph attributes plug-in dialog

(above) Each of the specified paragraph attributes has its own menu of settings and options. By default, the initial setting for each property is: “No Change”

All but the alignment property menus offer these two options:

NOTE: Immediately following each attribute title, placed within parens, is the current value of that attribute in the note.

IMPORTANT: Attribute changes are applied to all of the note text, not just a selection.

Here is a description of each of the paragraph attributes:

Return to: OmniFocus Plug-In Collection

Paragraph Attributes
   

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.of.paragraph-attributes", "version": "1.4", "description": "This plug-in will display and apply the paragraph attribute settings of the note of the selected project or task.", "label": "Note Style Paragraph Attributes", "shortLabel": "Paragraph Attributes", "paletteLabel": "Paragraph Attributes", "image": "parkingsign.circle.fill" }*/ (() => { var action = new PlugIn.Action(async function(selection, sender){ try { var shouldLog = false if(shouldLog){console.clear()} var item = selection.databaseObjects[0] // CREATE VIRTUAL TEXT OBJECT CONTAING CURRENT NOTE var noteObj = new Text("", baseStyle) noteObj.replace(noteObj.range, item.noteText) var nStyle = noteObj.style // GET ATTRIBUTE RUN RANGES var runRanges = noteObj.ranges(TextComponent.AttributeRuns) // TEXT OBJECTS AND STYLE var runRanges = noteObj.ranges(TextComponent.AttributeRuns) // CREATE FORM AND FORM ELEMENTS var txtAlgnCurVal = nStyle.get(Style.Attribute.ParagraphAlignment) var txtAlgnDsplyVal switch(String(txtAlgnCurVal)) { case "[object TextAlignment: Left]": txtAlgnDsplyVal = 'Left' break case "[object TextAlignment: Right]": txtAlgnDsplyVal = 'Right' break case "[object TextAlignment: Center]": txtAlgnDsplyVal = 'Center' break case "[object TextAlignment: Natural]": txtAlgnDsplyVal = 'Natural' break case "[object TextAlignment: Justified]": txtAlgnDsplyVal = 'Justified' break } paragraphAlignmentMenu = new Form.Field.Option( "paragraphAlignment", `Alignment (${txtAlgnDsplyVal})`, TextAlignment.all, null, null ) paragraphAlignmentMenu.allowsNull = true paragraphAlignmentMenu.nullOptionTitle = "No Change" spcBfrCurVal = nStyle.get(Style.Attribute.ParagraphSpacingBefore) spcBfrValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] spcBfrValueStrings = ["Default", "0", "4", "6", "8", "10", "12", "18", "24", "36"] spaceBeforeMenu = new Form.Field.Option( "spaceBefore", `Space Before (${spcBfrCurVal})`, spcBfrValues, spcBfrValueStrings, null ) spaceBeforeMenu.allowsNull = true spaceBeforeMenu.nullOptionTitle = "No Change" spcAftCurVal = nStyle.get(Style.Attribute.ParagraphSpacing) spcAftValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] spcAftValueStrings = ["Default", "0", "4", "6", "8", "10", "12", "18", "24", "36"] spaceAfterMenu = new Form.Field.Option( "spaceAfter", `Space After (${spcAftCurVal})`, spcAftValues, spcAftValueStrings, null ) spaceAfterMenu.allowsNull = true spaceAfterMenu.nullOptionTitle = "No Change" frstLnCurVal = nStyle.get(Style.Attribute.ParagraphFirstLineHeadIndent) frstLnValues = [0, 1, 2, 3, 4, 5, 6, 7] frstLnValueStrings = ["Default", "12", "18", "24", "36", "48", "64", "72"] firstLineIndentMenu = new Form.Field.Option( "firstLineIndent", `1st Line Indent (${frstLnCurVal})`, frstLnValues, frstLnValueStrings, null ) firstLineIndentMenu.allowsNull = true firstLineIndentMenu.nullOptionTitle = "No Change" headCurVal = nStyle.get(Style.Attribute.ParagraphHeadIndent) headValues = [0, 1, 2, 3, 4, 5, 6, 7] headValueStrings = ["Default", "0", "12", "24", "36", "48", "64", "72"] headIndentMenu = new Form.Field.Option( "headIndent", `Head Indent (${headCurVal})`, headValues, headValueStrings, null ) headIndentMenu.allowsNull = true headIndentMenu.nullOptionTitle = "No Change" tailCurVal = nStyle.get(Style.Attribute.ParagraphTailIndent) tailValues = [0, 1, 2, 3, 4, 5, 6, 7] tailValueStrings = ["Default", "0", "12", "24", "36", "48", "64", "72"] tailIndentMenu = new Form.Field.Option( "tailIndent", `Tail Indent (${tailCurVal})`, tailValues, tailValueStrings, null ) tailIndentMenu.allowsNull = true tailIndentMenu.nullOptionTitle = "No Change" lneHgtFctrCurVal = nStyle.get(Style.Attribute.ParagraphLineHeightMultiple) //console.log(lneHgtFctrCurVal) lneHgtFctrValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] lneHgtFctrValueStrings = ["Default", "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9", "2.0"] lineHeightFactorMenu = new Form.Field.Option( "lineHeightFactor", `Line Height Multiple (${lneHgtFctrCurVal})`, lneHgtFctrValues, lneHgtFctrValueStrings, null ) lineHeightFactorMenu.allowsNull = true lineHeightFactorMenu.nullOptionTitle = "No Change" lneSpcCurVal = nStyle.get(Style.Attribute.ParagraphLineSpacing) //console.log(lneSpcCurVal) lneSpcValues = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lneSpcValueStrings = ["Default", "0", "1", "2", "3", "4", "6", "8", "10", "12"] lineSpacingMenu = new Form.Field.Option( "lineSpacing", `Line Spacing (${lneSpcCurVal})`, lneSpcValues, lneSpcValueStrings, null ) lineSpacingMenu.allowsNull = true lineSpacingMenu.nullOptionTitle = "No Change" inputForm = new Form() inputForm.addField(paragraphAlignmentMenu) inputForm.addField(spaceBeforeMenu) inputForm.addField(spaceAfterMenu) inputForm.addField(firstLineIndentMenu) inputForm.addField(headIndentMenu) inputForm.addField(tailIndentMenu) inputForm.addField(lineHeightFactorMenu) inputForm.addField(lineSpacingMenu) formPrompt = "Note Paragraph Attributes:" buttonTitle = "Continue" formObject = await inputForm.show(formPrompt, buttonTitle) // retrieve attribute settings if(shouldLog){console.log(">>> RETRIEVING VALUES <<<")} paragraphAlignment = formObject.values["paragraphAlignment"] if(shouldLog){console.log("paragraphAlignment", paragraphAlignment)} spcBfrIndicator = formObject.values["spaceBefore"] spcBfrValue = spcBfrValueStrings[spcBfrIndicator] if(shouldLog){console.log("spcBfrValue", spcBfrValue)} spcAftIndicator = formObject.values["spaceAfter"] spcAftValue = spcAftValueStrings[spcAftIndicator] if(shouldLog){console.log("spcAftValue", spcAftValue)} firstLineIndentIndicator = formObject.values["firstLineIndent"] firstLineIndentValue = frstLnValueStrings[firstLineIndentIndicator] if(shouldLog){console.log("firstLineIndentValue", firstLineIndentValue)} headIndentIndicator = formObject.values["headIndent"] headIndentValue = headValueStrings[headIndentIndicator] if(shouldLog){console.log("headIndentValue", headIndentValue)} tailIndentIndicator = formObject.values["tailIndent"] tailIndentValue = tailValueStrings[tailIndentIndicator] if(shouldLog){console.log("tailIndentValue", tailIndentValue)} lineHeightMultipleIndicator = formObject.values["lineHeightFactor"] lineHeightMultiple = lneHgtFctrValueStrings[lineHeightMultipleIndicator] if(shouldLog){console.log("lineHeightMultiple", lineHeightMultiple)} lineSpacingIndicator = formObject.values["lineSpacing"] lineSpacingValue = lneSpcValueStrings[lineSpacingIndicator] if(shouldLog){console.log("lineSpacingValue", lineSpacingValue)} // SET ATTRIBUTE VALUES if(shouldLog){console.log(">>> APPLYING VALUES <<<")} var attsToModify = [] var valuesToApply = [] if(paragraphAlignment){ if(shouldLog){console.log("paragraphAlignment", paragraphAlignment)} if(paragraphAlignment === "Default"){ var valueToSet = Style.Attribute.ParagraphAlignment.defaultValue } else { var valueToSet = paragraphAlignment } attsToModify.push(Style.Attribute.ParagraphAlignment) valuesToApply.push(valueToSet) } if(spcBfrValue){ if(shouldLog){console.log("spcBfrValue", spcBfrValue)} if(spcBfrValue === "Default"){ var valueToSet = Style.Attribute.ParagraphSpacingBefore.defaultValue } else { var valueToSet = parseInt(spcBfrValue) } attsToModify.push(Style.Attribute.ParagraphSpacingBefore) valuesToApply.push(valueToSet) } if(spcAftValue){ if(shouldLog){console.log("spcAftValue", spcAftValue)} if(spcAftValue === "Default"){ var valueToSet = Style.Attribute.ParagraphSpacing.defaultValue } else { var valueToSet = parseInt(spcAftValue) } attsToModify.push(Style.Attribute.ParagraphSpacing) valuesToApply.push(valueToSet) } if(firstLineIndentValue){ if(shouldLog){console.log("firstLineIndentValue", firstLineIndentValue)} if(firstLineIndentValue === "Default"){ var valueToSet = Style.Attribute.ParagraphFirstLineHeadIndent.defaultValue } else { var valueToSet = parseInt(firstLineIndentValue) } attsToModify.push(Style.Attribute.ParagraphFirstLineHeadIndent) valuesToApply.push(valueToSet) } if(headIndentValue){ if(shouldLog){console.log("headIndentValue", headIndentValue)} if(headIndentValue === "Default"){ var valueToSet = Style.Attribute.ParagraphHeadIndent.defaultValue } else { var valueToSet = parseInt(headIndentValue) } attsToModify.push(Style.Attribute.ParagraphHeadIndent) valuesToApply.push(valueToSet) } if(tailIndentValue){ if(shouldLog){console.log("tailIndentValue", tailIndentValue)} if(tailIndentValue === "Default"){ var valueToSet = Style.Attribute.ParagraphTailIndent.defaultValue } else { var valueToSet = parseInt(tailIndentValue) } attsToModify.push(Style.Attribute.ParagraphTailIndent) valuesToApply.push(valueToSet) } if(lineHeightMultiple){ if(shouldLog){console.log("lineHeightMultiple", lineHeightMultiple)} if(lineHeightMultiple === "Default"){ var valueToSet = Style.Attribute.ParagraphLineHeightMultiple.defaultValue } else { var valueToSet = Number(lineHeightMultiple) } attsToModify.push(Style.Attribute.ParagraphLineHeightMultiple) valuesToApply.push(valueToSet) } if(lineSpacingValue){ if(shouldLog){console.log("lineSpacingValue", lineSpacingValue)} if(lineSpacingValue === "Default"){ var valueToSet = Style.Attribute.ParagraphLineSpacing.defaultValue } else { var valueToSet = Number(lineSpacingValue) } attsToModify.push(Style.Attribute.ParagraphLineSpacing) valuesToApply.push(valueToSet) } // APPLY THE SPECIFIED ATTRIBUTE SETTINGS runRanges.forEach(range => { runStyle = noteObj.styleForRange(range) attsToModify.forEach((att, index) => { valueToSet = valuesToApply[index] runStyle.set(att, valueToSet) }) }) // REPLACE NOTE WITH VIRTUAL OBJECT if(shouldLog){console.log(">>> REPLACING TEXT WITH NOTEOBJ <<<")} item.noteText.replace(item.noteText.range, noteObj) // REVEAL NOTE if(shouldLog){console.log("SHOW NOTE")} tree = document.windows[0].content tree.nodeForObject(item).expandNote(false) } catch(err){ if(!err.causedByUserCancelling){ console.log(err.name, err.message) } } }); action.validate = function(selection, sender){ // validation code // selection options: tasks, projects, folders, tags, allObjects return (selection.tasks.length === 1 || selection.projects.length === 1 ) }; return action; })();