Plug-In: Paragraph Attributes ![Plug-ins are compatible with Apple Vision Pro 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)
(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:
- No Change • When this option is chosen, no changes will be made to the paragraph attribute.
- Default • When this option is chosen, the default value for the paragraph attribute will be applied to the note text.
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:
- Alignment (TextAlignment) • The text alignment of the paragraph. Natural text alignment is realized as left or right alignment depending on the line sweep direction of the first script contained in the paragraph.
- First Line Head Indent (Number) • The indentation of the first line of the paragraph. A paragraph’s “head” is the side from which you read. This property contains the distance (in points) from the leading margin of a text container to the beginning of the paragraph’s first line. This value is always nonnegative.
- Head Indent (Number) • The indentation of the paragraph’s lines other than the first. A paragraph’s “head” is the side from which you read. This property contains the distance (in points) from the leading margin of a text container to the beginning of lines other than the first. This value is always nonnegative.
- Tail Indent (Number) • If positive, this value is the distance from the leading margin (for example, the left margin in left-to-right text). If 0 or negative, it’s the distance from the trailing margin.
- Line Height Multiple (Number) • The natural line height of the paragraph is multiplied by this factor (if positive) before being constrained by minimum and maximum line height. The default value of this property is 0.0.
- Line Spacing (Number) • The distance in points between the bottom of one line fragment and the top of the next. This value is always nonnegative.
- Spacing (Number) • The space after the end of the paragraph. This property contains the space (measured in points) added at the end of the paragraph to separate it from the following paragraph. This value is always nonnegative. The space between paragraphs is determined by adding the previous paragraph’s Paragraph Spacing and the current paragraph’s Paragraph Spacing Before.
- Spacing Before (Number) • The distance between the paragraph’s top and the beginning of its text content. This property contains the space (measured in points) between the paragraph’s top and the beginning of its text content. The default value of this property is 0.0.
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 = falseif(shouldLog){console.clear()}var item = selection.databaseObjects[0]// CREATE VIRTUAL TEXT OBJECT CONTAING CURRENT NOTEvar noteObj = new Text("", baseStyle)noteObj.replace(noteObj.range, item.noteText)var nStyle = noteObj.style// GET ATTRIBUTE RUN RANGESvar runRanges = noteObj.ranges(TextComponent.AttributeRuns)// TEXT OBJECTS AND STYLEvar runRanges = noteObj.ranges(TextComponent.AttributeRuns)// CREATE FORM AND FORM ELEMENTSvar txtAlgnCurVal = nStyle.get(Style.Attribute.ParagraphAlignment)var txtAlgnDsplyValswitch(String(txtAlgnCurVal)) {case "[object TextAlignment: Left]":txtAlgnDsplyVal = 'Left'breakcase "[object TextAlignment: Right]":txtAlgnDsplyVal = 'Right'breakcase "[object TextAlignment: Center]":txtAlgnDsplyVal = 'Center'breakcase "[object TextAlignment: Natural]":txtAlgnDsplyVal = 'Natural'breakcase "[object TextAlignment: Justified]":txtAlgnDsplyVal = 'Justified'break}paragraphAlignmentMenu = new Form.Field.Option("paragraphAlignment",`Alignment (${txtAlgnDsplyVal})`,TextAlignment.all,null,null)paragraphAlignmentMenu.allowsNull = trueparagraphAlignmentMenu.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 = truespaceBeforeMenu.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 = truespaceAfterMenu.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 = truefirstLineIndentMenu.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 = trueheadIndentMenu.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 = truetailIndentMenu.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 = truelineHeightFactorMenu.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 = truelineSpacingMenu.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 settingsif(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 VALUESif(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 SETTINGSrunRanges.forEach(range => {runStyle = noteObj.styleForRange(range)attsToModify.forEach((att, index) => {valueToSet = valuesToApply[index]runStyle.set(att, valueToSet)})})// REPLACE NOTE WITH VIRTUAL OBJECTif(shouldLog){console.log(">>> REPLACING TEXT WITH NOTEOBJ <<<")}item.noteText.replace(item.noteText.range, noteObj)// REVEAL NOTEif(shouldLog){console.log("SHOW NOTE")}tree = document.windows[0].contenttree.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, allObjectsreturn (selection.tasks.length === 1 || selection.projects.length === 1 )};return action;})();