(I realize I’m inefficiently declaring a bunch of temporary variables I don’t need, but this version is written for utter clarity, over efficiency.)
The code does successfully upcase everything, but given this input, where the italic text is locally-applied styling…
This is a simple test.
…the result is…
THIS IS A SIMPLE TEST.
…with the italic styling of “simple” missing.
I can see in the console output that it processed 'This is a ', then 'simple', then ' test.', so it seems that using TextComponent.AttributeRuns is the right way to go, but I don’t understand why I’m not managing to “carry along” the existing styling using styleForRange().
You’ll see the same behavior in Pages and TextEdit for the transformations. This isn’t a problem with your script, but it is the nature of text transformations in general. The text attributes applied to the first character of the string are used for text transformations.
If you need the local style attributes, I’m not sure there is an easy way to do that while using any of the transformations. You could try getting the styles before transformation and reapplying them at the end.
I don’t quite understand, however. Are you saying that in my currStyle = textObj.styleForRange(range) line, I’m not actually retrieving all the styling that exists in the range?
Or is the problem that my newTextObj = new Text(newText,currStyle) line isn’t effectively applying that styling to the new Text object?
And can you please explain what you mean when you say:
The text attributes applied to the first character of the string are used for text transformations.
My understanding is that I’m getting the current style that exists in each range, and applying it to every character of my replacement text.
But we may just be talking about different things :)
I mean that if you select text in the application and apply a text transformation manually in any application, the text itself is replaced without retaining the locally applied text attributes. That is expected for how the feature works (in multiple applications on macOS).
Steps:
Select your text that says “This is a simple test” and apply a transformation (in TextEdit, Pages, or OmniOutliner).
Transform the selected text to UpperCase.
Notice the italic is not kept. If you change the first character (the T in This) to italic, all of the characters will be in italic.
What I mean is UpperCase, and other text transformation features, do not carry along attributes in general. This is not a problem with your script or a bug, but a general limitation of text transformations.
And I think my problem is here–I expect currStyle to be the style of a given block of text, but in every case, currStyle.locallyDefinedAtrributes is undefined.
I suspect my expectations are wrong here–can you (or anyone) help?
I figured out a solution, but don’t understand why it is necessary.
Above, when I create my new Text object, I provide a style (currStyle)…
newTextObj = new Text(newText,currStyle)
…and then replace the old text in the range…
textObj.replace(range,newTextObj)
…which, surprisingly (to me, anyway), results in unstyled replacement text.
Here’s my fix: if I then follow that up by re-applying that same currStyle style to that same range…
textObj.styleForRange(range).setStyle(currStyle)
…then everything is perfect.
For the record, the sample “Replace Matched Words” code near the bottom of https://omni-automation.com/omnioutliner/text-object.html has the same problem–it’s specifically noted there that in the sample code “…the replacement text object is styled using the same style as the text object it replaces.”. However, that code doesn’t preserve styling either, and is also fixed by the line of code I added above.
Based on what I’ve learned from this adventure, here’s sample code for modifying text (it currently upcases text, but is easily modified) in an outline without losing styling–I hope it helps someone!
targetItems = selection.items
targetItems.forEach(function(item){
textObj = item.valueForColumn(document.outline.outlineColumn)
textObj.ranges(TextComponent.AttributeRuns).reverse().forEach(function(range){
origRangeStyle = textObj.styleForRange(range)
textObj.replace(range,new Text(textObj.textInRange(range).string.toUpperCase(),origRangeStyle))
// Next line reasserts same styling already asserted in line above; odd, but needed in OO 5.4.2
textObj.styleForRange(range).setStyle(origRangeStyle)
})
})
Note that the .reverse() isn’t actually needed in this case, since the length of replaced text never changes, but I’m leaving it in there for safety, since it isn’t very expensive to execute and may prevent frustration if someone (maybe me!) modifies this code for other use.
Though I still might be misunderstanding something, I’ve reported the failure of Text.replace() to successfully insert styled text in this case as a potential bug, so that last line may not be necessary in the future.
Thanks a lot for this question. I have also faced this question for quite a long. But after researching so much I got an option and I am writing that for your reference you can check that also - You can also check more things related to tcs rate on sale of goods.
‘alphabet’.toUpperCase(); // ‘ALPHABET’
‘ABC’.toUpperCase(); // ‘ABC’
Text(‘Aposté todo a tu risa y perdí la mía. - JZ’.toUpperCase(), style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold)).
<View>
<Text style={{ textTransform: 'uppercase'}}>
React Native .toUpperCase() function works fine in a string but if you used the numbers or other non-string data types, it doesn't work. The error will have occurred. Basically, you can check also [tcs rate on sale of goods]( https://www.exactlly.com/blog/index.php/tax-collected-at-source-on-sale-of-goods-detailed-guide/).
Below Two are string properties:
<Text>{props.complexity.toUpperCase()}</Text>
<Text>{props.affordability.toUpperCase()}</Text>
This text should be uppercased.
</Text>
<Text style={{ textTransform: 'capitalize'}}>
Mixed:{' '}
<Text style={{ textTransform: 'lowercase'}}>
lowercase{' '}
</Text>
</Text>
</View>