28 Replies Latest reply on Oct 30, 2017 11:50 AM by Jarda Bereza

    Changing color of text found with regex

    tusharde Level 1

      Hi,

      I have multiple text layers in the document. I would like to filter through the contents of each text layer with regex and change the color of the found result.

      In the example below I would like to find all the hastags in the text layer and change the color to blue.

       

      Example:

      This is a really long piece of text copy and #hashtag more copy here #anotherhastag #hashtagNo3

       

      I've written a few scripts for indesign that involve GREP(regex) and it's fairly simple to change the color of the found results. I can't seem to find a solution for this in photoshop.

       

      Thanks

        • 1. Re: Changing color of text found with regex
          c.pfaffenbichler Level 8

          I recommend abandoning the idea to do this in Photoshop, Indesign is oriented towards sophisticated text editing, so better to do it there.

           

          In Photoshop changing parts of text within a Type Layer necessitates using AM code that can become quite unwieldy in my experience.

          • 2. Re: Changing color of text found with regex
            tusharde Level 1

            Thanks for the quick response.Unfortunately, I have to use photoshop for this job. So I'm stuck with photoshop. By "AM code" do you mean action manager? Any pointers in that direction will be very helpful.

            Unfortunately, I can only use photoshop for this job. So I'm stuck with photoshop. By "AM code" do you mean action manager? Any pointers in that direction will be very helpful.

            Thanks

            • 3. Re: Changing color of text found with regex
              c.pfaffenbichler Level 8

              Yes, I meant Action Manager code.

               

              Try recording changing the color of one word in a larger text in a Type Layer with ScriptingListener.plugin and see how well manageable the resulting code seems to you.

              • 4. Re: Changing color of text found with regex
                c.pfaffenbichler Level 8

                I forgot to add: If there is any possibility that some parts within the type layer vary at all with regard to type properties (size, leading, font etc.) do include some such varying elements in your test.

                • 5. Re: Changing color of text found with regex
                  tusharde Level 1

                  Will give that a shot. Thank you.

                  One thing I am stumbling upon in my tests is finding a word with regex and affecting just those results. Any tips on how I would go about that? For example, in a regex search like this "foundText" ends up as just plain text. I can't seem to affect the properties of that "foundText". Like color size etc. Is this the right approach? Is there a better way?

                   

                  var foundText = textLayer.match(new RegExp("#hashtag", "i"))
                  
                  • 6. Re: Changing color of text found with regex
                    c.pfaffenbichler Level 8

                    The foundText (the result of the match) is a String, it is not part of the actual Type Layer.

                    • 7. Re: Changing color of text found with regex
                      SuperMerlin Level 5

                      Here is an example changing text when the text layer is selected. Changing colour of a section of text has been done in the past by xbytor

                      and he might chip in, but I would not attempt it!

                       

                      if(activeDocument.activeLayer.kind == LayerKind.TEXT){

                      var textContent = activeDocument.activeLayer.textItem.contents;

                      activeDocument.activeLayer.textItem.contents = textContent.replace(/mine/ig,"his");

                      }

                      • 8. Re: Changing color of text found with regex
                        Jarda Bereza Level 3

                        So do you want to do something like Font Remaping script here: Magic scripts for Photoshop  but with searched text and colors instead font family?

                         

                        I agree with others. This can be very difficult.

                        You need to:

                        1) read whole text layer action descriptor

                        2) find all your strings and position where they start and where is end of string

                        3) if text layer has multiple styles, there is list of these styles and index where they start and where they end. So you need to read this descriptor, make copy and change color and position indexes and then put this descriptors into list and this list replace in original layer descritor

                        4) finaly you can use "set descriptor" action manager code and change the layer.

                         

                        Like this:

                        2017-09-26_184756.jpg

                         

                        Before:

                        2017-09-26_183731.jpg

                        After:

                        2017-09-26_183925.jpg

                        1 person found this helpful
                        • 9. Re: Changing color of text found with regex
                          tusharde Level 1

                          Wow. This is very helpful. Thank you. I'm going to give it a crack and see where I end up.
                          Clearly, this looks like a "long walk for a ham sandwich". But it'll be worth the learning experience. I guess??

                          I'll hit you up with questions as I go along.

                           

                          Jarda, what app/plugin did you use in your images? It looks incredibly helpful. Where can i get that?

                           

                          Thanks again, c.pfaffenbichler,  SuperMerlinand Jarda Bereza.

                          • 10. Re: Changing color of text found with regex
                            Jarda Bereza Level 3

                            It's my own tool. Not public yet, but maybe it could be public soon.

                             

                            It's based on this code: GitHub - JavierAroche/descriptor-info: JSX module to recursively get all the properties in an ActionDescriptor used in A…

                             

                            And this code:

                            descriptor to JSON is already buil-in in Photoshop · Issue #10 · JavierAroche/descriptor-info · GitHub

                             

                            So this should help you. You also can explore my script with align to baseline and text columns. I am getting here descriptor, changing it and then setting back. Magic scripts for Photoshop

                            • 11. Re: Changing color of text found with regex
                              tusharde Level 1

                              Great. Thanks much,

                              Those are some great scripts. Congrats.

                              • 12. Re: Changing color of text found with regex
                                xbytor2 Level 4

                                Somebody mention me?

                                 

                                 

                                SourceForge is acting up so you will need to download xtools:

                                SourceForge

                                 

                                The files of interest are xtools/xlib/Text.jsx  and xtools/xlib/TextTest.jsx. It can be done but it requires a bit of work.

                                 

                                Here is the relevant code from TextTest.jsx that shows you how it's done.

                                 

                                var layer = doc.layers[layerName];
                                  doc.activeLayer = layer;
                                  var opts = new TextOptions(layer.textItem);
                                  opts.contents = "123567875688\radsfasfasdfasdfasdf\n(&#^&^#$";

                                  // construct the styles
                                  var s1 = new TextStyle("ArialMT");
                                  var s2 = new TextStyle("Courier-Bold", 30, Text.toRGBColor(0, 255, 0));

                                  // this style will use the default font...
                                  var s3 = new TextStyle(undefined, 42, Text.toRGBColor(255, 0, 0));

                                  // superscript test
                                  var s0 = new TextStyle(s1);
                                  s0.baseline = PSString.superScript;

                                  // Now create the set of ranges to apply the styles over
                                  var ranges = new TextStyleRanges();
                                  ranges.add(new TextStyleRange(0, 1, s0));
                                  ranges.add(new TextStyleRange(1, opts.contents.length, s1));
                                  ranges.add(new TextStyleRange(5, 10, s2));
                                  ranges.add(new TextStyleRange(7, 15, s3));
                                  ranges.add(new TextStyleRange(25, undefined, s2));

                                  opts.ranges = ranges;
                                  Text.modifyTextLayer(doc, opts, doc.layers[layerName]);

                                 

                                As somebody said before, InDesign is a more appropriate tool.

                                4 people found this helpful
                                • 13. Re: Changing color of text found with regex
                                  oliverIntergrafika Level 2

                                  I have a TODO line to implement low level text manipulation in my extension. But, as my collegues suggested, the AM structure is a  bedrock layer under the swamp guarded by hydras. I don't have enough patience and passion and not smart enough to get to the lowest layers.

                                   

                                  I wish Adobe would start the whole PS source code from scratch again and implement it a way which is allowing us to properly script the app.

                                   

                                  Thanks xbytor2 for the .jsx code, ill try it!

                                  • 14. Re: Changing color of text found with regex
                                    tusharde Level 1

                                    Wow. Thanks for sharing these scripts. They are incredibly helpful. Very much appreciated.

                                    • 15. Re: Changing color of text found with regex
                                      tusharde Level 1

                                      Question: What is the best way for me to get the text ranges from the text layer with a regex search. My current solution returns a string which isn't very helpful. Is regex the right approach or is there a better way?

                                      Example:

                                      Below are the contents of the text layer and I want to find all the hashtags.

                                       

                                      This is a really long piece of text copy and #hashtag more copy here #anotherhastag #hashtagNo3

                                       

                                      var foundText = textLayer.match(new RegExp("\S*#(?:\[[^\]]+\]|\S+)", "i"))  
                                      
                                      • 16. Re: Changing color of text found with regex
                                        Jarda Bereza Level 3

                                        I would use something like "IndexOf" but this will be more than 1 line of code.

                                        • 17. Re: Changing color of text found with regex
                                          SuperMerlin Level 5

                                          Something like...

                                          var s = activeDocument.activeLayer.textItem.contents;
                                          var re = /(?:^|\W)#(\w+)(?!\w)/g, match, matches = [];
                                          while (match = re.exec(s)) {
                                            matches.push([[match[0].replace(/^\s+|\s+$/g,'')],[match.index+1],[match[0].replace(/^\s+|\s+$/g,'').length]]);
                                          }
                                          for(var a in matches){
                                              $.writeln("Word found = " + matches[a][0] + " start = " + matches[a][1] + " length = " +matches[a][2]);
                                              }
                                          
                                          
                                          
                                          • 19. Re: Changing color of text found with regex
                                            tusharde Level 1

                                            Hi xbytor2

                                            Thank you for sharing all those scripts. I've been looking through the code and they've been a huge learning resource.

                                            I tried to implement the TextTest.jsx script into my own version but I've been running into an issue.

                                            When I run the below script I get this error: "Error: General Photoshop error occurred. This functionality may not be available in this version of Photoshop."

                                             

                                            Is it something to do with this line in the script?

                                            Text.modifyTextLayer(doc, opts, doc.layers[layerName]);
                                            

                                             

                                             

                                            Here's the whole script.

                                             

                                            //
                                            // HashtagColor_v1.jsx
                                            //
                                            //============================================================================
                                            //@includepath "~/Documents/xtools"
                                            //
                                            //@include "xlib/PSConstants.js"
                                            //@include "xlib/stdlib.js"
                                            //@include "xlib/Text.jsx"
                                            //@include "xlib/Action.js"
                                            //@include "xlib/xml/atn2xml.jsx"
                                            //
                                            
                                            
                                            
                                            
                                            function colorHashtag(doc) {
                                              var layerName = "Test Layer";
                                              var layer = doc.layers[layerName];
                                              doc.activeLayer = layer;
                                              var opts = new TextOptions(layer.textItem);
                                              opts.contents = layer.textItem.contents;
                                            
                                            
                                              //opts.contents = "123567875688\radsfasfasdfasdfasdf\n(&#^&^#$";
                                            
                                            
                                              // construct the styles
                                              var s1 = new TextStyle("ArialMT");
                                              var s2 = new TextStyle("Courier-Bold", 30, Text.toRGBColor(0, 255, 0));
                                            
                                            
                                              // this style will use the default font...
                                              var s3 = new TextStyle(undefined, 42, Text.toRGBColor(255, 0, 0));
                                            
                                            
                                              // superscript test
                                              var s0 = new TextStyle(s1);
                                              s0.baseline = PSString.superScript;
                                            
                                            
                                              // Now create the set of ranges to apply the styles over
                                              var ranges = new TextStyleRanges();
                                              ranges.add(new TextStyleRange(0, 1, s0));
                                              ranges.add(new TextStyleRange(1, opts.contents.length, s1));
                                              ranges.add(new TextStyleRange(5, 10, s2));
                                              ranges.add(new TextStyleRange(7, 15, s3));
                                              ranges.add(new TextStyleRange(25, undefined, s2));
                                            
                                            
                                              opts.ranges = ranges;
                                              Text.modifyTextLayer(doc, opts, doc.layers[layerName]);
                                            }
                                            
                                            
                                            Text.test = function(doc) {
                                              var doc;
                                              if (app.documents.length) {
                                                doc = app.activeDocument
                                              }
                                              colorHashtag(doc);
                                            }
                                            
                                            
                                            Text.test();
                                            
                                            
                                            "HashtagColor_v1.jsx";
                                            
                                            • 20. Re: Changing color of text found with regex
                                              tusharde Level 1

                                              Upon further trial and error, I noticed that the "modifyTextLayer" function runs without issues on a text layer created by the script, but has issues with existing text layers created directly in the photoshop document.

                                              So in your TextTest.jsx file, the newTextLayerDemo function creates a text layer. The rest of the script works when working with that text later. But in my version of the script, I am trying to work with an existing text layer in photoshop (ideally, the currently selected text layer), and I get that error.

                                               

                                              Any thoughts or how to solve this?

                                              • 21. Re: Changing color of text found with regex
                                                Jarda Bereza Level 3

                                                I will tell you secret.

                                                You can:

                                                0) read layer actionDescriptor

                                                1) use native function for converting actionDescriptor into JSON

                                                2) use eval() on JSON string and create javascript object

                                                3) modify regular JS object with well known object opertions. You need to do same thing as in my screenshot.

                                                4) convert JS object into JSON string with ".toSource()" method

                                                5) convert JSON string into ActionDescriptor with native function

                                                6) and finally you can put modified descriptor into "executeAction"

                                                 

                                                I think I will create small library for this workflow.

                                                2 people found this helpful
                                                • 22. Re: Changing color of text found with regex
                                                  tusharde Level 1

                                                  Thanks Jarda. This is way above my punching weight, but I'm going to give it a shot. I have managed to get up to step 4. But I am struggling with the step 5 and 6. At the moment I'm keeping it pretty basic: change the color of the entire text to red. Once I get the core functionality working I'll jump into figuring out how to change text ranges to a different color.

                                                  Bear in mind that I've written the script referencing different sources across the forms. So it's probably not the cleanest and most efficient way to do it.

                                                  Any help on how I can get steps 5 and 6 working would be great.

                                                   

                                                  Thanks

                                                  #include "./helpers/JSON.jsx"
                                                  
                                                  // 0) read layer actionDescriptor
                                                  var ref = new ActionReference();
                                                  ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
                                                  var desc = executeActionGet(ref)
                                                  var convertDesc = new ActionDescriptor();
                                                  convertDesc.putObject(stringIDToTypeID("object"), stringIDToTypeID("object"), desc);
                                                  var jsonDesc = executeAction(stringIDToTypeID("convertJSONdescriptor"), convertDesc, DialogModes.NO);
                                                  
                                                  // 1) use native function for converting actionDescriptor into JSON
                                                  jsonDesc.getString(stringIDToTypeID("json"));
                                                  
                                                  // 2) use eval() on JSON string and create javascript object
                                                  var obj = JSON.parse(jsonDesc.getString(stringIDToTypeID("json")));
                                                  
                                                  // 3) modify regular JS object with well known object opertions. You need to do same thing as in my screenshot.
                                                  obj["textKey"]["textStyleRange"][0]["textStyle"]["baseParentStyle"]["color"]["red"] = 255;
                                                  
                                                  // 4) convert JS object into JSON string with ".toSource()" method
                                                  var objToStr = JSON.stringify(obj);
                                                  alert(objToStr);
                                                  
                                                  // 5) convert JSON string into ActionDescriptor with native function
                                                  
                                                  // 6) and finally you can put modified descriptor into "executeAction"
                                                  
                                                  • 23. Re: Changing color of text found with regex
                                                    Jarda Bereza Level 3

                                                    Here is first version of my tool:

                                                     

                                                    GitHub - jardicc/ActionManagerHumanizer: This tool will reveal for you occult mystery of Photoshop ActionDescriptors and…

                                                     

                                                    Works good for me. You probably will need CC 2015.5 and higher

                                                    Keep in mind that pure AM will be faster something about 10-30ms per conversion into JS object and back.

                                                    • 24. Re: Changing color of text found with regex
                                                      tusharde Level 1

                                                      Wow! Thank you. I'll play with it now.

                                                      Much appreciated.

                                                      • 25. Re: Changing color of text found with regex
                                                        Jarda Bereza Level 3

                                                        Here is working code:

                                                         

                                                        /**
                                                         * Set range and change text style
                                                         *
                                                         * @param {ActionDescriptor} sourceRef Layer reference
                                                         * @param {number} from The index of string to set the range from
                                                         * @param {number} to The index of string to set the range to
                                                         * @param {string} face The string of font family name
                                                         * @param {string} weight The string of font style name
                                                         * @param {string} unit The unit of the type.  "pt","px", or "mm"
                                                         * @param {number} size The size of the font.
                                                         *      Points: 0.01pt to 1296.00pt
                                                         *      Pixels: 0.01px to 1296.00px
                                                         *      Millimeters: 0.00mm to 457.19mm
                                                         * @param {array} arrayTextColor The array of RGB color [red,green,blue]. 0 to 255
                                                         *
                                                         * @return {PlayObject} The action descriptor of the text style.
                                                         *
                                                         * Preconditions:
                                                         * Select a text layer
                                                         *
                                                         * Examples:
                                                         * setRangeAndChangeTextStyle(0,1,"Helvetica","Bold","pt",60,[200,100,150]);
                                                         * setRangeAndChangeTextStyle(0,3,"","","pt",20,[200,100,150]);
                                                         */
                                                        desc = {
                                                                    "null": {
                                                        "_enum": "ordinal",
                                                        "_ref": "layer",
                                                        "_value": "targetEnum"
                                                        },
                                                                    "to": {
                                                                        "_obj": "textLayer",
                                                                        "_value": {
                                                                            "textStyleRange": [
                                                                                {
                                                                                    "_obj": "textStyleRange",
                                                                                    "_value": {
                                                                                        "from": 5,
                                                                                        "to": 15,
                                                                                        "textStyle": {
                                                                                            "_obj": "textStyle",
                                                                                            "_value": {
                                                                                                "fontName": "Arial",
                                                                                                "fontStyleName": "Bold",
                                                                                                "size": {
                                                        "_unit": "pixelsUnit",
                                                        "_value": 20
                                                        },
                                                                                                "color": {
                                                        "_obj": "RGBColor",
                                                        "blue": 255,
                                                        "grain": 0,
                                                        "red": 17.984434962272644
                                                        }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            ]
                                                                        }
                                                                    }
                                                                }
                                                        
                                                        
                                                        var descMod = Humanizer.objectToDescriptor(desc)[1];
                                                        var data = executeAction( stringIDToTypeID( "set" ), descMod, DialogModes.NO );
                                                        

                                                         

                                                        You will need to include my "Humanizer" tool.

                                                        Pros:

                                                        1) don't need specify font face

                                                        2) not sure if it is same for size or color

                                                        3) you will get new whole action descriptor in "data" variable

                                                        4) you don't need care about style ranges around. Photoshop changes "from" and "to" indexes automaticaly.

                                                        5) you could maybe add more ranges into textStyle ranges.

                                                        1 person found this helpful
                                                        • 26. Re: Changing color of text found with regex
                                                          tusharde Level 1

                                                          Thanks Jarda. This is great!

                                                          Sorry for the late reply. Just got around to it.

                                                          Testing it out shortly.

                                                          • 27. Re: Changing color of text found with regex
                                                            tusharde Level 1

                                                            Hi Jarda,

                                                            Thank you for sharing the script. Very much appreciated.

                                                            I've been trying to figure out how to make the script work without specifying the font face or the font size. But can't seem to get it to work. The text defaults to "Myriad Pro" and a very small size.

                                                            I was deleting the "font name" and "size" from the desc object in your script. Am I doing it wrong?

                                                             

                                                            Thanks

                                                            • 28. Re: Changing color of text found with regex
                                                              Jarda Bereza Level 3

                                                              I comment is empty string for fontface and fot weight in parameter. So I try to keep these property but place "" as value.

                                                              I am not sure about font-size. Try some kinds of empty values. Btw save your data, Photoshop may crash :-D