Style
Beginning with OmniFocus 4, the textual content of project and task notes supports the standard Rich Text Format (RFT). This means that text in notes are Text Objects that can be sized, colored, and styled, and may also contain specialized text objects such as Link Objects.
While the inline RTF codes and markings remain invisible to the user, the textual contents of notes may be defined and controlled through Omni Automation scripts and plug-ins.
The following documentation details the support for the new Style class. Other classes used in processing note text are Text and Color, that are documented on this website as well.
IMPORTANT: Styling for task and project notes is on a “per-note” basis, meaning that there is no ability to change the global note settings. However, with the use of plug-ins and voice commands, changing the look of a project or task note can be a very easy process!
IMPORTANT: Colors are always modeled using values appropriate for rendering in Light mode, and they dynamically adapt as you switch between Light and Dark modes. For example, to make text appear “lighter” in color in Dark Mode, make it “darker” in the default Light Mode.
Before beginning the examination of the Style class, here’s an example script for creating a “note style” that works in both Light and Dark Mode, and adjust certain parameters based upon the type of device. To run, select a single task or project with a long note, then copy the script and paste into the Automation Console in OmniFocus. Press the Return key to see the change!
Note Style: “Legal Pad”
(async () => {
try {
console.log("DEVICE TYPE:", Device.current.type)
var sel = document.windows[0].selection
items = sel.databaseObjects.filter(
item => (item instanceof Project || item instanceof Task)
)
if(items.length === 1){
var item = sel.databaseObjects[0]
// reveal note
tree = document.windows[0].content
tree.nodeForObject(item).expandNote(false)
// identify objects
noteObj = item.noteText
var nStyle = noteObj.style
// reset local attributes values to defaults to avoid conflicts from previous style
localAtts = nStyle.locallyDefinedAttributes
attKeys = localAtts.map(att => att.key)
attKeys.forEach(thisKey => {
var targetAtt = localAtts.find(att => {
return att.key === thisKey
})
try {
nStyle.set(targetAtt, targetAtt.defaultValue)
}
catch(err){console.error(targetAtt.key, err.message)}
})
// apply formatting
nStyle.set(Style.Attribute.FontFamily, 'American Typewriter')
nStyle.set(Style.Attribute.FontItalic, false)
nStyle.set(Style.Attribute.FontWeight, 4)
typeSize = (Device.current.type === DeviceType.iPhone) ? 14:18
nStyle.set(Style.Attribute.FontSize, typeSize)
console.log("TYPESIZE:", typeSize)
nStyle.set(Style.Attribute.BackgroundColor, null)
nStyle.set(Style.Attribute.FontFillColor, Color.darkGray)
LHFactor = (Device.current.type === DeviceType.iPhone) ? 1.5:2
nStyle.set(Style.Attribute.ParagraphLineHeightMultiple, LHFactor)
console.log("LINE HEIGHT MULTIPLE:", LHFactor)
nStyle.set(Style.Attribute.ParagraphSpacingBefore, 36)
nStyle.set(Style.Attribute.KerningAdjustment, 1)
var tailIndent = (Device.current.type === DeviceType.mac) ? 72:36
if (Device.current.type === DeviceType.iPhone){
nStyle.set(Style.Attribute.ParagraphTailIndent, 0)
console.log("TAILINDENT:", 0)
} else {
nStyle.set(Style.Attribute.ParagraphTailIndent, tailIndent)
console.log("TAILINDENT:", tailIndent)
}
} else {
throw {
name: "Selection Issue",
message: "Please select a single project or task."
}
}
}
catch(err){
new Alert(err.name, err.message).show()
}
})();
NOTE: more Note Templates are available at the end of this documentation.
Next, the examination of the Style class begins an overview of the properties and functions of the Style class.
Instance Properties
Here are the basic properties of a style.
fontFillColor (Color) • The color used to fill text. Setting the color to null will remove the setting for this style.
link (URL or nil r/o) • Returns the URL link for a style, or null if there is no link applied. If the style represents a file attachment and there is no specific link attribute set, the URL for the file attachment will be returned.
locallyDefinedAttributes (Array of Style.Attribute r/o) • Returns an array of the Style.Attributes defined on this Style.
namedStyles (Array of NamedStyle r/o) • Returns the NamedStyles that are directly associated with this Style. If a style attribute lookup doesn’t find a value in the local style, then the named styles will be searched. (NOT AVAILABLE IN OMNIFOCUS)
Instance Functions
An instance of style can be manipulated by the following set of methods, beginning with a set of commands for clearing, getting, and setting its style attributes:
clear() • Removes all the locally applied style attribute values for this Style.
get(attribute:Style.Attribute) --> Object or nil • Looks up the value for the specified style attribute locally, in the cascading and inherited styles, and finally falling back to the default value for the style attribute.
set(attribute:Style.Attribute, value:Object or nil) --> Boolean • Sets (or clears) the value for the given style attribute. Styles that cascade from this one will inherit this value, if they don’t define their own value or have a closer ancestor style that does. Returns true if a change was actually made, false otherwise. Throws an error if the key does not map to a known attribute, or if the value is of the wrong type for the specified attribute.
localValueForAttribute(attribute:Style.Attribute) --> Object or nil • Looks up the value for the specified style attribute locally, returning null if it is not set.
addNamedStyle(namedStyle:NamedStyle) • Adds the specified NamedStyle to the set of named styles to include in this Style. If the style is already present, or if this would create a loop (adding two NamedStyles to each other’s list of named styles), an error will be thrown. (NOT AVAILABLE IN OMNIFOCUS)
removeNamedStyle(namedStyle:NamedStyle) • Removes the specified NamedStyle from the set of named styles to include in this Style. If the style is not present, an error will be thrown. (NOT AVAILABLE IN OMNIFOCUS)
influencedBy(otherStyle:Style) --> Boolean • Returns true if the receiver is influenced, directly or indirectly from the passed Style.
setStyle(style:Style) • Updates all the attributes and inherited styles on the receiver to be the same as the argument Style.
Here's an example script demonstrating how to set the value a a note’s locally defined attributes to their default values:
Reset Local Attributes to Default
sel = document.windows[0].selection
items = sel.databaseObjects.filter(
item => (item instanceof Project || item instanceof Task)
)
if(items.length === 1){
noteObj = items[0].noteText
nStyle = noteObj.style
localAtts = nStyle.locallyDefinedAttributes
attKeys = localAtts.map(att => att.key)
attKeys.forEach(thisKey => {
var targetAtt = localAtts.find(att => {
return att.key === thisKey
})
try {
nStyle.set(targetAtt, targetAtt.defaultValue)
}
catch(err){console.error(targetAtt.key, err.message)}
})
}
Style Attributes
A style attribute is a particular property or characteristic of a style. For example, font size and paragraph alignment are two attributes that can be adjusted using scripts. Here is the list of the attributes of a style instance:
TIP: Examples for setting and resetting style attributes can be found in the OmniFocus Voice Commmands collection.
BackgroundColor (Color) • The styles’s background color.
“BackGroundColor” Attribute
styleInst.set(Style.Attribute.BackGroundColor, Color.white)
BaselineOffset (Number) • The value of this attribute is a number indicating the character’s offset from the baseline, in points. The default value is 0.
“BaselineOffset” Attribute
styleInst.set(Style.Attribute.BaselineOffset, 3) // up
styleInst.set(Style.Attribute.BaselineOffset, 0) // normal
styleInst.set(Style.Attribute.BaselineOffset, -3) // down
BaselineSuperscript (Boolean) • If this attribute’s value is true, then a superscript attribute is applied to the styled text, raising its baseline offset by a predefined amount.
“BaselineSuperscript” Attribute
// turn on
styleInst.set(Style.Attribute.BaselineSuperscript, true)
// turn off
styleInst.set(Style.Attribute.BaselineSuperscript, false)
Expansion (Boolean) • This attribute, when applied, has the dramatic effect of squashing and stretching text.
“Expansion” Attribute
// turn on
styleInst.set(Style.Attribute.Expansion, true)
// turn off
styleInst.set(Style.Attribute.Expansion, false)
FontCondensed (Boolean) • If set to true, then the condensed version of the font will be used IF the condensed typeface is installed and available.
FontFamily (String) • The family name of the font—for example, “Times” or “Helvetica.”
FontFillColor (Color) • Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
FontFixedPitch (Boolean) • A Boolean value indicating whether all glyphs in the font have the same advancement. The value of this property is true when all glyphs have the same advancement or false when they do not.
FontItalic (Boolean) • A Boolean value indicating whether or not the font is italicized.
FontName (String) • The full name of the font, as used in PostScript language code—for example, “Times-Roman” or “Helvetica-Oblique.” TIP: On macOS, use the Font Book application to look up relevant font information.
FontNarrow (Boolean) • A Boolean value indicating whether or not the narrow or condensed version of the font family is applied.
FontSize (Number) • The point size of the font.
FontStrokeColor (Color) • Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
FontStrokeWidth (Number) • In the OmniOutliner interface this attribute shows as font border width, and is a numeric value in points indicating the extra thickness to be applied to effected text.
FontWeight (Number) • An integer (generally from 1 to 9) indicating how thick or thin the font is.
Font Attributes
styleInst.set(Style.Attribute.FontCondensed, false)
styleInst.set(Style.Attribute.FontFamily, 'Helvetica Neue')
styleInst.set(Style.Attribute.FontFillColor, Color.white)
styleInst.set(Style.Attribute.FontFixedPitch, false)
styleInst.set(Style.Attribute.FontItalic, true)
styleInst.set(Style.Attribute.FontName, 'HelveticaNeue-MediumItalic')
styleInst.set(Style.Attribute.FontNarrow, false)
styleInst.set(Style.Attribute.FontSize, 14)
styleInst.set(Style.Attribute.FontStrokeColor, Color.red)
styleInst.set(Style.Attribute.FontStrokeWidth, 2)
styleInst.set(Style.Attribute.FontWeight, 6)
IMPORTANT: to set the font of a style to a specific variation, use a combination of the FontFamily, FontWeight, and FontItalic attributes rather than the FontName attribute:
Set Font to Specific Variation
// Set a style’s font to “Helvetica Neue UltraLight Italic”
styleInst.set(Style.Attribute.FontFamily, 'Helvetica Neue')
styleInst.set(Style.Attribute.FontItalic, true)
styleInst.set(Style.Attribute.FontWeight, 1)
styleInst.set(Style.Attribute.FontSize, 24)
NOTE: Values for the fontWeight property vary between font families. Here are the font weight values for Helvetica Neue:
Helvetica Neue UltraLight = 1
Helvetica Neue Thin = 2
Helvetica Neue Light = 3
Helvetica Neue Book = 4
Helvetica Neue Regular = 5
Helvetica Neue Medium = 6
Helvetica Neue Demi-Bold = 7
Helvetica Neue SemiBold = 8
Helvetica Neue Bold = 9
Helvetica Neue ExtraBold = 10
Helvetica Neue Heavy = 11
Helvetica Neue Black = 12
Helvetica Neue Ultra = 13
Helvetica Neue Extrablack = 14
NOTE: to set the font family to the default system UI font:
Set Font Family to Default System UI Font
task = document.windows[0].selection.tasks[0]
// OmniFocus uses the system UI font as its default
task.noteText.style.set(Style.Attribute.FontFamily, Style.Attribute.FontFamily.defaultValue)
// (FYI) The system UI font reference
task.noteText.style.set(Style.Attribute.FontFamily, ".AppleSystemUIFont")
KerningAdjustment (Number) • A numeric value in points describing an extra increase (loosen) or decrease (tighten) in space between the characters effected by the style.
“KerningAdjustment” Attribute
//-> increase (loosen)
styleInst.set(Style.Attribute.KerningAdjustment, 3)
//-> decrease (tighten)
styleInst.set(Style.Attribute.KerningAdjustment, -3)
//-> default
styleInst.set(Style.Attribute.KerningAdjustment, 0)
LigatureSelection (LigatureStyle) • A typographic ligature is a combination of two or more letters into a single symbol, such as the characters f and l (fl) and their corresponding ligature fl. The LigatureSelection attribute is used to determine the set of ligatures to use with the style.
“LigatureSelection” Attribute
styleInst.set(Style.Attribute.LigatureSelection, LigatureStyle.All)
styleInst.set(Style.Attribute.LigatureSelection, LigatureStyle.Essential)
styleInst.set(Style.Attribute.LigatureSelection, LigatureStyle.Standard)
Link (URL) • Interestingly, OmniOutliner styles can be assigned URLs (links) that are triggered when the styled objects are tapped or clicked. The links can be to a webpage or even Omni Automation scripts! See the script links section for more information about using encoded scripts as style links.
“Link” Attribute
url = URL.fromString('https://omni-automation.com')
styleInst.set(Style.Attribute.Link, url)
Obliqueness (Number) • A numeric value indicating how much to skew the text display to the right (positive number) or left (negative number). Generally, the best values are within a range of -1 to 1.
“Obliqueness” Attribute
// lean right
styleInst.set(Style.Attribute.Obliqueness, .25)
// lean left
styleInst.set(Style.Attribute.Obliqueness, -.25)
// none
styleInst.set(Style.Attribute.Obliqueness, 0)
Paragraph Attributes
ParagraphAlignment (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.
“ParagraphAlignment” Attribute
styleInst.set(Style.Attribute.ParagraphAlignment, TextAlignment.Center)
styleInst.set(Style.Attribute.ParagraphAlignment, TextAlignment.Justified)
styleInst.set(Style.Attribute.ParagraphAlignment, TextAlignment.Left)
styleInst.set(Style.Attribute.ParagraphAlignment, TextAlignment.Natural)
styleInst.set(Style.Attribute.ParagraphAlignment, TextAlignment.Right)
ParagraphBaseWritingDirection (WritingDirection) • The base writing direction for the paragraph. If you the value of this property is Natural, the receiver resolves the writing direction to either LeftToRight or RightToLeft, depending on the direction for the user’s language preference setting.
“ParagraphBaseWritingDirection” Attribute
styleInst.set(Style.Attribute.ParagraphBaseWritingDirection, WritingDirection.LeftToRight)
styleInst.set(Style.Attribute.ParagraphBaseWritingDirection, WritingDirection.Natural)
styleInst.set(Style.Attribute.ParagraphBaseWritingDirection, WritingDirection.RightToLeft)
ParagraphDefaultTabInterval (Number) • This property represents the default tab interval in points. Tabs after the last specified in ParagraphTabStops are placed at integer multiples of this distance (if positive). Default value is 0.0.
“ParagraphDefaultTabInterval” Attribute
styleInst.set(Style.Attribute.ParagraphDefaultTabInterval, 72)
//-> true
styleInst.get(Style.Attribute.ParagraphDefaultTabInterval)
//-> 72
ParagraphFirstLineHeadIndent (Number) • The indentation of the first line of the paragraph. 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.
ParagraphHeadIndent (Number) • The indentation of the paragraph’s lines other than the first. 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.
ParagraphLineHeightMultiple (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.
ParagraphLineSpacing (Number) • The distance in points between the bottom of one line fragment and the top of the next. This value is always nonnegative.
ParagraphMaximumLineHeight (Number) • The paragraph’s maximum line height. This property contains the maximum height in points that any line in the receiver will occupy, regardless of the font size or size of any attached graphic. This value is always nonnegative. The default value is 0. Glyphs and graphics exceeding this height will overlap neighboring lines; however, a maximum height of 0 implies no line height limit. Although this limit applies to the line itself, line spacing adds extra space between adjacent lines.
ParagraphMinimumLineHeight (Number) • The paragraph’s minimum height. This property contains the minimum height in points that any line in the paragraph will occupy, regardless of the font size or size of any attached graphic. This value is always nonnegative
ParagraphSpacing (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 ParagraphSpacing and the current paragraph’s ParagraphSpacingBefore.
ParagraphSpacingBefore (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.
ParagraphTabStops (Comma-Delimited String) • '28L,56L,86R' Numeric values are in points. Tab-alignment types are: L = left tab, R = right tab, C = center tab, D = decimal tab. By default, set to 12 left-aligned tabs, spaced by 28.0 points.
“ParagraphTabStops” Attribute
styleInst.get(Style.Attribute.ParagraphTabStops)
//-> 28L,
56L, 84L, 112L, 140L, 168L, 196L, 224L, 252L, 280L, 308L, 336L styleInst.set(Style.Attribute.ParagraphTabStops, '72L,144L,216R')
styleInst.get(Style.Attribute.ParagraphTabStops)
//-> 72L,144L,216R
Creating TabStop String for 6 Financial Columns
tabWidth = 128
firstTabOffset = 192
columnCount = 6
tabStops = String(firstTabOffset) + "D"
for (i = 1; i < columnCount; i++) {
tabStops += "," + String(firstTabOffset + (i * tabWidth)) + "D"
}
console.log("TABSTOPS:", tabStops)
//--> TABSTOPS: 192D,320D,448D,576D,704D,832D
ParagraphTailIndent (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.
“ParagraphTailIndent” Attribute
styleInst.set(Style.Attribute.ParagraphTailIndent, 72)
ShadowBlurRadius (Number) • A numeric value indicating the amount of diffusion of the text shadow.
“ShadowBlurRadius” Attribute
styleInst.set(Style.Attribute.ShadowBlurRadius, 2.5)
ShadowColor (Color) • A color value to assign to the shadow of the text. Use null for no color.
“ShadowColor” Attribute
styleInst.set(Style.Attribute.ShadowColor, Color.black)
ShadowOffset (Point) • A point indicating the horizontal and vertical offsets in points from the shadowed text. For the horizontal offset, negative values move the shadow left, positive values move the shadow right. For the vertical offset, positive values move the shadow up, negative values move the shadow down.
“ShadowOffset” Attribute
// offset the shadow to the lower right (horizontal, vertical)
styleInst.set(Style.Attribute.ShadowOffset, new Point(3, -4))
StrikethroughAffinity (UnderlineAffinity) • Indicates how the text is to have a strikethrough applied, either through all text or through words only, leaving the spaces between intact.
StrikethroughColor (Color) • The color value of the strikethrough line or lines.
StrikethroughPattern (UnderlinePattern) • The pattern of the strikethrough line or lines.
StrikethroughStyle (UnderlineStyle) • The style of the strikethrough line or lines. For example, single, double, thick, or none.
UnderlineAffinity (UnderlineAffinity) • Indicates how the text is to have a underline applied, either through all text or through words only, leaving the spaces between intact.
UnderlineColor (Color) • The color value of the underline line or lines.
UnderlinePattern (UnderlinePattern) • The pattern of the underline line or lines.
UnderlineStyle (UnderlineStyle) • The style of the underline line or lines. For example, single, double, thick, or none.
Striketrough
// Single Line
styleInst.set(Style.Attribute.StrikethroughStyle, UnderlineStyle.Single)
// No Strikethrough
styleInst.set(Style.Attribute.StrikethroughStyle, null)
Style Attribute Instance Properties
defaultValue (Object r/o) • Returns the default value that will be used when a style has no local value for this attribute, nor do any of its associated styles.
key (String r/o) • Returns the string used to identify this attribute when calling get or set on a Style instance.
Here are a list of all the keys for the available style attributes:
Style Attribute Keys
["text-background-color","baseline-offset","baseline-superscript","font-expansion","font-condensed","font-family","font-fill","font-fixed-pitch","font-italic","font-name","font-narrow","font-size","font-stroke","font-stroke-width","font-weight","kerning-adjust","ligature-selection","link","font-obliqueness","paragraph-alignment","paragraph-base-writing-direction","paragraph-tab-stop-interval","paragraph-first-line-head-indent","paragraph-head-indent","paragraph-line-height-multiple","paragraph-line-spacing","paragraph-maximum-line-height","paragraph-minimum-line-height","paragraph-spacing","paragraph-spacing-before","paragraph-tab-stops","paragraph-tail-indent","shadow-radius","shadow-color","shadow-offset","strikethrough-affinity","strikethrough-color","strikethrough-pattern","strikethrough-style","underline-affinity","underline-color",UnderlinePattern,"underline-style"]
Here’s a script that logs the local style attributes of the current note:
Determining Current Style Adjustments
sel = document.windows[0].selection
items = sel.databaseObjects.filter(
item => (item instanceof Project || item instanceof Task)
)
if(items.length === 1){
noteObj = items[0].noteText
nStyle = noteObj.style
localAtts = nStyle.locallyDefinedAttributes
attKeys = localAtts.map(att => att.key)
attKeys.forEach(thisKey => {
targetAtt = localAtts.find(att => {
return att.key === thisKey
})
attValue = nStyle.get(targetAtt)
if (attValue instanceof Color){
colorString = `Color.RGB(${attValue.red}, ${attValue.green}, ${attValue.blue}, ${attValue.alpha})`
console.log(thisKey + ":", colorString)
} else {
console.log(thisKey + ":", attValue)
}
})
} else {
throw {
name: "Selection Issue",
message: "Please select a single project or task."
}
}
TIP: Install the attribute logging plug-in and add it to the Console window toolbar for quick access to style information for the note of the selected project or task:
Default Values
Here's a script that uses the defaultValue property to derive the default values for fonts:
Default Font Style Attribute Values
Style.Attribute.FontFamily.defaultValue
//--> Helvetica
Style.Attribute.FontName.defaultValue
//--> Helvetica
Style.Attribute.FontSize.defaultValue
//--> 12
Style.Attribute.FontWeight.defaultValue
//--> 5
clr = Style.Attribute.FontFillColor.defaultValue
console.log([clr.red, clr.green, clr.blue])
//--> [0, 0, 0]
clr = Style.Attribute.FontStrokeColor.defaultValue
console.log([clr.red, clr.green, clr.blue])
//--> [0, 0, 0]
Style.Attribute.FontStrokeWidth.defaultValue
//--> 0
Style.Attribute.FontCondensed.defaultValue
//--> false
Style.Attribute.FontItalic.defaultValue
//--> false
Style.Attribute.FontNarrow.defaultValue
//--> false
Here's a script that resets the current value of an attribute to its default value:
Set Style Attribute Value to Default Value for Attribute
styleInst.set(Style.Attribute.FontSize, Style.Attribute.FontSize.defaultValue)
Here’s a variation that resets all style attributes to default values for the selected note:
Reset All Attributes to Default Values
var attributes = [Style.Attribute.BackgroundColor, Style.Attribute.BaselineOffset, Style.Attribute.BaselineSuperscript, Style.Attribute.Expansion, Style.Attribute.FontCondensed, Style.Attribute.FontFamily, Style.Attribute.FontFillColor, Style.Attribute.FontFixedPitch, Style.Attribute.FontItalic, Style.Attribute.FontName, Style.Attribute.FontNarrow, Style.Attribute.FontSize, Style.Attribute.FontStrokeColor, Style.Attribute.FontStrokeWidth, Style.Attribute.FontWeight, Style.Attribute.KerningAdjustment, Style.Attribute.LigatureSelection, Style.Attribute.Link, Style.Attribute.Obliqueness, Style.Attribute.ParagraphAlignment, Style.Attribute.ParagraphDefaultTabInterval, Style.Attribute.ParagraphFirstLineHeadIndent, Style.Attribute.ParagraphHeadIndent, Style.Attribute.ParagraphLineHeightMultiple, Style.Attribute.ParagraphLineSpacing, Style.Attribute.ParagraphMaximumLineHeight, Style.Attribute.ParagraphMinimumLineHeight, Style.Attribute.ParagraphSpacing, Style.Attribute.ParagraphSpacingBefore, Style.Attribute.ParagraphTabStops, Style.Attribute.ParagraphTailIndent, Style.Attribute.ShadowBlurRadius, Style.Attribute.ShadowColor, Style.Attribute.ShadowOffset, Style.Attribute.StrikethroughAffinity, Style.Attribute.StrikethroughColor, Style.Attribute.StrikethroughPattern, Style.Attribute.StrikethroughStyle, Style.Attribute.UnderlineAffinity, Style.Attribute.UnderlineColor, Style.Attribute.UnderlinePattern, Style.Attribute.UnderlineStyle]
var sel = document.windows[0].selection
var items = sel.databaseObjects.filter(item => {
if(item instanceof Project || item instanceof Task){return item}
})
if(items.length === 1){
noteObj = items[0].noteText
var nStyle = noteObj.styleForRange(noteObj.range)
attributes.forEach(att => {
nStyle.set(att, att.defaultValue)
})
} else {
throw {
name: "Selection Issue",
message: "Please select a single project or task."
}
}
NOTE: There’s an OmniFocus voice command for appending plain-text from the clipboard to the note of the selected project or task.
UnderlineAffinity
A class whose properties indicate how the text is to be underlined.
ByWord (r/o) • Underline only the words, but not the space between them.
None (r/o) • Underline the entire range.
UnderlinePattern
A class whose properties indicate how the line pattern to be used in underlining text.
Dash (r/o) • Dashed line.
DashDot (r/o) • Alternating dashes and dots.
DashDotDot (r/o) • Alternating dashes and pairs of dots.
Dot (r/o) • Dotted line.
Solid (r/o) • A continuous line.
UnderlineStyle
Underline style specifiers.
Double (r/o) • Two lines.
None (r/o) • No underline.
Single (r/o) • A single line.
Thick (r/o) • A single thick line.
LigatureStyle
A class whose properties indicate the set of ligatures to be applied to the text.
All (r/o) • Use all of the available ligatures.
Essential (r/o) • Use ligatures that are required for proper rendering of text.
Standard (r/o) • Use the default ligatures for the given script.
TextAlignment
A class whose properties indicate the text alignment options for the styled paragraphs.
Center (r/o) • Visually center aligned.
Justified (r/o) • Fully-justified.
Left (r/o) • Visually left aligned.
Natural (r/o) • Use the default alignment based on the characters in the text.
Right (r/o) • Visually right aligned.
WritingDirection
A class whose properties indicate the available writing directions to use for the styled text.
LeftToRight (r/o) • Text is laid out from left to right.
Natural (r/o) • The text direction follows the Unicode bi-directional algorithm.
RightToLeft (r/o) • Text is laid out from right to left.
Saving Note to RTF File
Here's a plug-in that can be used to save the copied contents of a formated note to an RTF file in the OmniFocus documents folder:
Save Clipboard Text to App Documents Folder
/*{
"type": "action",
"targets": ["omnifocus", "omnigraffle", "omniplan", "omnioutliner"],
"author": "Otto Automator",
"identifier": "com.omni-automation.all.write-clip-text-to-app-documents",
"version": "1.2",
"description": "Writes the text content of the clipboard to a file in the Omni app’s local Documents folder",
"label": "Clip Text to App Documents Folder",
"shortLabel": "Save to App Documents",
"paletteLabel": "Save to App Documents",
"image": "doc.on.clipboard.fill"
}*/
(() => {
var action = new PlugIn.Action(async function(selection, sender){
try {
inputForm = new Form()
fileNameField = new Form.Field.String(
"fileBaseName",
"File Name",
null,
null
)
inputForm.addField(fileNameField)
fileTypes = ["Text (plain)", "TaskPaper", "RTF", "HTML", "JavaScript", "SVG"]
nameExtensions = ["txt", "taskpaper", "rtf", "html", "js", "svg"]
savingTypeMenu = new Form.Field.Option(
"nameExtension",
"Text File Type",
nameExtensions,
fileTypes,
nameExtensions[0]
)
inputForm.addField(savingTypeMenu)
if (Device.current.mac){
shouldOpenFileField = new Form.Field.Checkbox(
"shouldOpenFile",
"Open file in default application",
null
)
inputForm.addField(shouldOpenFileField)
}
inputForm.validate = function(formObject){
textValue = formObject.values['fileBaseName']
return (textValue && textValue.length > 0) ? true:false
}
formPrompt = `Clipboard to ${app.name} Documents`
buttonTitle = "Continue"
formObject = await inputForm.show(formPrompt, buttonTitle)
fileBaseName = formObject.values["fileBaseName"]
nameExtension = formObject.values["nameExtension"]
fileName = fileBaseName + "." + nameExtension
if (Device.current.mac){
var shouldOpenFile = formObject.values["shouldOpenFile"]
}
folderURL = URL.documentsDirectory
fileURL = folderURL.appendingPathComponent(fileName)
if (nameExtension === "rtf"){
textData = Pasteboard.general.dataForType(TypeIdentifier.rtf)
} else {
textData = Data.fromString(Pasteboard.general.string, StringEncoding.UTF8)
}
wrapper = FileWrapper.withContents(fileName, textData)
wrapper.write(fileURL, [FileWrapper.WritingOptions.Atomic], null)
if (Device.current.mac){
if(shouldOpenFile){fileURL.open()}
}
} catch(err){console.error(err.message)}
});
action.validate = function(selection, sender){
return (Pasteboard.general.hasStrings)
};
return action;
})();
Note Style Plug-Ins
Here are some more note templates to try! Typefaces are available on all Apple devices.
NOTE: for style clarity all existing locally defined attributes are set to default values before applying the new styling.
- Legal Pad (American Typewriter) • Simulates double-spaced typed legal documents.
- Relaxed Cursive (Noteworthy) • Moderate-sized cursive with a high x-height and a slight spacing between characters.
- Hand Written (Bradley Hand) • Uses Apple’s Bradley Hand typeface to simulate a tight hand-written appearance.
- Syllabus (Avenir Next) • Very readable san-serif with a low x-height in a comfortable spacing. Hold down the Option key when launching the plug-in to overide font fill, stroke, and underline colors. Hold down the Shift key to overide font weight and italics.
- 3-Column Financial (Helvetica) • Begins with a header column followed by three data columns with decimal tab stops.
- Reset to Defaults • Resets all style attributes to default values.
- Paragraph Attributes • Displays current settings and controls for adjusting paragraph attributes. (shown below)
TIP: this collection is also available as Voice Control commands.
Note Style Templates
The following script and plug-in templates can be used to create your own note style tools. Each template already contains the necessary code for identifying the note of the selected project or task, as well as to clear any previous settings before applying the new attributes settings.
Note Style Script Templateagenda://note/WelcomeSection-Share
(async () => {
try {
console.log("DEVICE TYPE:", Device.current.type)
var sel = document.windows[0].selection
items = sel.databaseObjects.filter(
item => (item instanceof Project || item instanceof Task)
)
if(items.length === 1){
console.log("DEVICE:", Device.current.type)
var item = sel.databaseObjects[0]
// reveal note
tree = document.windows[0].content
tree.nodeForObject(item).expandNote(false)
// identify selected note and style
noteObj = item.noteText
var nStyle = noteObj.style
// reset local attributes values to defaults
localAtts = nStyle.locallyDefinedAttributes
attKeys = localAtts.map(att => att.key)
attKeys.forEach(thisKey => {
var targetAtt = localAtts.find(att => {
return att.key === thisKey
})
try {
nStyle.set(targetAtt, targetAtt.defaultValue)
}
catch(err){console.error(targetAtt.key, err.message)}
})
// FORMATTING STATEMENTS GO HERE
} else {
throw {
name: "Selection Issue",
message: "Please select a single project or task."
}
}
}
catch(err){
new Alert(err.name, err.message).show()
}
})();
Note Style Plug-In Template
/*{
"type": "action",
"targets": ["omnifocus"],
"author": "Your Name Goes Here",
"identifier": "com.YouOrCompany.of.name-for-plug-in",
"version": "1.0",
"description": "A plug-in for changing the note style of the selected project or task",
"label": "Plug-In Menu Item Title",
"shortLabel": "Short Item Title",
"paletteLabel": "Toolbar Item Title",
"image": "wand.and.stars"
}*/
(() => {
const action = new PlugIn.Action(async function(selection, sender){
// action code
try {
console.log("DEVICE:", Device.current.type)
var item = selection.databaseObjects[0]
// reveal note
tree = document.windows[0].content
tree.nodeForObject(item).expandNote(false)
// identify selected note and style
noteObj = item.noteText
var nStyle = noteObj.style
// reset local attributes values to defaults
localAtts = nStyle.locallyDefinedAttributes
attKeys = localAtts.map(att => att.key)
attKeys.forEach(thisKey => {
var targetAtt = localAtts.find(att => {
return att.key === thisKey
})
try {
nStyle.set(targetAtt, targetAtt.defaultValue)
}
catch(err){console.error(targetAtt.key, err.message)}
})
// FORMATTING STATEMENTS GO HERE
}
catch(err){
console.error(err.name, err.message)
new Alert(err.name, err.message).show()
}
});
action.validate = function(selection, sender){
// validation code
return (selection.projects.length === 1 || selection.tasks.length === 1)
};
return action;
})();