Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
Thanks Jarda. This is great!
Sorry for the late reply. Just got around to it.
Testing it out shortly.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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 😄
Copy link to clipboard
Copied
Hi Jarda,
Thank you so much for all your answers! I'm running into an issue when trying to use your script, I put the Humanizer.jsx into the Script list of Photoshop 2018 but I still get the issue "Line: 65 -> var descMod = Humanizer.objectToDescriptor(desc)[1]; " when trying to run the script * Set range and change text style
What am I doing wrong?
Also, before I continue any further, do you think it would be cumbersome to modify the script to parse all text layers and find numbers to change the font?
Thanks!
Copy link to clipboard
Copied
It may be useful for you (replies No. 11 & No. 18): Script to Select and Raster similar text-layer (font-family + font weight)
Copy link to clipboard
Copied
You need the setFormatting() function, described in this Adobe blog post from 2011 http://blogs.adobe.com/cssdk/2011/01/formatting-text-ranges-in-photoshop.html
The main thing to note is that anything not set will revert to the document default - eg. if you change the colour but don't set the typeface, the colour will change but the typeface will change back to whatever is default. I'm not aware of any way to 'get' granular formatting from text, so this works best on a textItem that's initially all one style.
It's easy enough to add parameters to change by lifting code out of Script Listener output.
My example usage here, followed by the function as I'm using it.
var text = docRef.activeLayer.textItem.contents;
// changes font for single or double quotes (') (")
for (var l = 0; l < text.length; l++ ) {
if (text
== '"' || text == "'") { setFormatting(l, l+1, "ITC Avant Garde Gothic Std", "Bold Condensed", 120, 80, 100, 0, [255,255,255]);
}
}
function setFormatting(start, end, fontName, fontStyle, fontSize, vScale, hScale, baseline, colorArray) {
//Sanity checking: is the active layer a text layer?
if(app.activeDocument.activeLayer is ArtLayer){
var activeLayer = app.activeDocument.activeLayer;
if(activeLayer.kind == LayerKind.TEXT){
//More checking: does the text layer have content, and are start and end set to reasonable values?
if((activeLayer.textItem.contents != "")&&(start >= 0)&&(end <= activeLayer.textItem.contents.length)){
var idsetd = app.charIDToTypeID( "setd" );
var action = new ActionDescriptor();
var idnull = app.charIDToTypeID( "null" );
//The action reference specifies the active text layer.
var reference = new ActionReference();
var idTxLr = app.charIDToTypeID( "TxLr" );
var idOrdn = app.charIDToTypeID( "Ordn" );
var idTrgt = app.charIDToTypeID( "Trgt" );
reference.putEnumerated( idTxLr, idOrdn, idTrgt );
action.putReference( idnull, reference );
var idT = app.charIDToTypeID( "T " );
var textAction = new ActionDescriptor();
var idTxtt = app.charIDToTypeID( "Txtt" );
//actionList contains the sequence of formatting actions.
var actionList = new ActionList();
//textRange sets the range of characters to format.
var textRange = new ActionDescriptor();
var idFrom = app.charIDToTypeID( "From" );
textRange.putInteger( idFrom, start );
textRange.putInteger( idT, end );
var idTxtS = app.charIDToTypeID( "TxtS" );
//The "formatting" ActionDescriptor holds the formatting. It should be clear that you can
//add other attributes here--just get the relevant lines (usually 2) from the Script Listener
//output and graft them into this section.
var formatting = new ActionDescriptor();
//Font name.
var idFntN = app.charIDToTypeID( "FntN" );
formatting.putString( idFntN, fontName );
//Font style.
var idFntS = app.charIDToTypeID( "FntS" );
formatting.putString( idFntS, fontStyle );
//Font size.
var idSz = app.charIDToTypeID( "Sz " );
var idPnt = app.charIDToTypeID( "#Pnt" );
formatting.putUnitDouble( idSz, idPnt, fontSize );
//Vertical Scale
var idVrtS = charIDToTypeID( "VrtS");
formatting.putDouble( idVrtS, vScale);
//Horizontal Scale
var idHrzS = charIDToTypeID( "HrzS" );
formatting.putDouble (idHrzS, hScale);
//Vertical Baseline Height
var idBsln = charIDToTypeID( "Bsln" );
var idPxl = charIDToTypeID( "#Pxl" );
formatting.putUnitDouble( idBsln, idPxl, baseline );
//Fill color (as an RGB color).
var idClr = app.charIDToTypeID( "Clr " );
var colorAction = new ActionDescriptor();
var idRd = app.charIDToTypeID( "Rd " );
colorAction.putDouble( idRd, colorArray[0] );
var idGrn = app.charIDToTypeID( "Grn " );
colorAction.putDouble( idGrn, colorArray[1]);
var idBl = app.charIDToTypeID( "Bl " );
colorAction.putDouble( idBl, colorArray[2] );
var idRGBC = app.charIDToTypeID( "RGBC" );
formatting.putObject( idClr, idRGBC, colorAction );
//end color.
//
textRange.putObject( idTxtS, idTxtS, formatting );
actionList.putObject( idTxtt, textRange );
textAction.putList( idTxtt, actionList );
action.putObject( idT, idTxLr, textAction );
app.executeAction( idsetd, action, DialogModes.NO );
}
}
}